/* 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 <stdint.h>
#include <pthread.h>
#include <sys/types.h>
#include <cutils/mspace.h>
#include "tinyutils/KeyedVector.h"
#include "tinyutils/smartpointer.h"
namespace android {
// ----------------------------------------------------------------------------
class AssemblyKeyBase {
public:
virtual ~AssemblyKeyBase() { }
virtual int compare_type(const AssemblyKeyBase& key) const = 0;
};
template <typename T>
class AssemblyKey : public AssemblyKeyBase
{
public:
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:
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:
static mspace getMspace();
void ensureMbaseExecutable();
mutable int32_t mCount;
uint32_t* mBase;
size_t mSize;
};
// ----------------------------------------------------------------------------
class CodeCache
{
public:
// pretty simple cache API...
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() { };
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