/* libs/pixelflinger/codeflinger/CodeCache.h ** ** Copyright 2006, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #ifndef ANDROID_CODECACHE_H #define ANDROID_CODECACHE_H #include <atomic> #include <stdint.h> #include <pthread.h> #include <sys/types.h> #include "utils/KeyedVector.h" #include "tinyutils/smartpointer.h" namespace android { using namespace tinyutils; // ---------------------------------------------------------------------------- class AssemblyKeyBase { public: virtual ~AssemblyKeyBase() { } virtual int compare_type(const AssemblyKeyBase& key) const = 0; }; template <typename T> class AssemblyKey : public AssemblyKeyBase { public: explicit AssemblyKey(const T& rhs) : mKey(rhs) { } virtual int compare_type(const AssemblyKeyBase& key) const { const T& rhs = static_cast<const AssemblyKey&>(key).mKey; return android::compare_type(mKey, rhs); } private: T mKey; }; // ---------------------------------------------------------------------------- class Assembly { public: explicit Assembly(size_t size); virtual ~Assembly(); ssize_t size() const; uint32_t* base() const; ssize_t resize(size_t size); // protocol for sp<> void incStrong(const void* id) const; void decStrong(const void* id) const; typedef void weakref_type; private: mutable std::atomic<int32_t> mCount; uint32_t* mBase; size_t mSize; }; // ---------------------------------------------------------------------------- class CodeCache { public: // pretty simple cache API... explicit CodeCache(size_t size); ~CodeCache(); sp<Assembly> lookup(const AssemblyKeyBase& key) const; int cache(const AssemblyKeyBase& key, const sp<Assembly>& assembly); private: // nothing to see here... struct cache_entry_t { inline cache_entry_t() { } inline cache_entry_t(const sp<Assembly>& a, int64_t w) : entry(a), when(w) { } sp<Assembly> entry; mutable int64_t when; }; class key_t { friend int compare_type( const key_value_pair_t<key_t, cache_entry_t>&, const key_value_pair_t<key_t, cache_entry_t>&); const AssemblyKeyBase* mKey; public: key_t() { }; explicit key_t(const AssemblyKeyBase& k) : mKey(&k) { } }; mutable pthread_mutex_t mLock; mutable int64_t mWhen; size_t mCacheSize; size_t mCacheInUse; KeyedVector<key_t, cache_entry_t> mCacheData; friend int compare_type( const key_value_pair_t<key_t, cache_entry_t>&, const key_value_pair_t<key_t, cache_entry_t>&); }; // KeyedVector uses compare_type(), which is more efficient, than // just using operator < () inline int compare_type( const key_value_pair_t<CodeCache::key_t, CodeCache::cache_entry_t>& lhs, const key_value_pair_t<CodeCache::key_t, CodeCache::cache_entry_t>& rhs) { return lhs.key.mKey->compare_type(*(rhs.key.mKey)); } // ---------------------------------------------------------------------------- }; // namespace android #endif //ANDROID_CODECACHE_H