mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-08-20 23:53:44 +08:00
bring over phonelibs minus frida-gum and qsml
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 _LIBS_UTILS_ANDROID_THREADS_H
|
||||
#define _LIBS_UTILS_ANDROID_THREADS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <utils/ThreadDefs.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C API
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Create and run a new thread.
|
||||
extern int androidCreateThread(android_thread_func_t, void *);
|
||||
|
||||
// Create thread with lots of parameters
|
||||
extern int androidCreateThreadEtc(android_thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName,
|
||||
int32_t threadPriority,
|
||||
size_t threadStackSize,
|
||||
android_thread_id_t *threadId);
|
||||
|
||||
// Get some sort of unique identifier for the current thread.
|
||||
extern android_thread_id_t androidGetThreadId();
|
||||
|
||||
// Low-level thread creation -- never creates threads that can
|
||||
// interact with the Java VM.
|
||||
extern int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName,
|
||||
int32_t threadPriority,
|
||||
size_t threadStackSize,
|
||||
android_thread_id_t *threadId);
|
||||
|
||||
// set the same of the running thread
|
||||
extern void androidSetThreadName(const char* name);
|
||||
|
||||
// Used by the Java Runtime to control how threads are created, so that
|
||||
// they can be proper and lovely Java threads.
|
||||
typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName,
|
||||
int32_t threadPriority,
|
||||
size_t threadStackSize,
|
||||
android_thread_id_t *threadId);
|
||||
|
||||
extern void androidSetCreateThreadFunc(android_create_thread_fn func);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Extra functions working with raw pids.
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
// Change the priority AND scheduling group of a particular thread. The priority
|
||||
// should be one of the ANDROID_PRIORITY constants. Returns INVALID_OPERATION
|
||||
// if the priority set failed, else another value if just the group set failed;
|
||||
// in either case errno is set. Thread ID zero means current thread.
|
||||
extern int androidSetThreadPriority(pid_t tid, int prio);
|
||||
|
||||
// Get the current priority of a particular thread. Returns one of the
|
||||
// ANDROID_PRIORITY constants or a negative result in case of error.
|
||||
extern int androidGetThreadPriority(pid_t tid);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// C++ API
|
||||
#ifdef __cplusplus
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Create and run a new thread.
|
||||
inline bool createThread(thread_func_t f, void *a) {
|
||||
return androidCreateThread(f, a) ? true : false;
|
||||
}
|
||||
|
||||
// Create thread with lots of parameters
|
||||
inline bool createThreadEtc(thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName = "android:unnamed_thread",
|
||||
int32_t threadPriority = PRIORITY_DEFAULT,
|
||||
size_t threadStackSize = 0,
|
||||
thread_id_t *threadId = 0)
|
||||
{
|
||||
return androidCreateThreadEtc(entryFunction, userData, threadName,
|
||||
threadPriority, threadStackSize, threadId) ? true : false;
|
||||
}
|
||||
|
||||
// Get some sort of unique identifier for the current thread.
|
||||
inline thread_id_t getThreadId() {
|
||||
return androidGetThreadId();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
#endif // __cplusplus
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#endif // _LIBS_UTILS_ANDROID_THREADS_H
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_UTILS_ATOMIC_H
|
||||
#define ANDROID_UTILS_ATOMIC_H
|
||||
|
||||
#include <cutils/atomic.h>
|
||||
|
||||
#endif // ANDROID_UTILS_ATOMIC_H
|
||||
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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_BASIC_HASHTABLE_H
|
||||
#define ANDROID_BASIC_HASHTABLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/SharedBuffer.h>
|
||||
#include <utils/TypeHelpers.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/* Implementation type. Nothing to see here. */
|
||||
class BasicHashtableImpl {
|
||||
protected:
|
||||
struct Bucket {
|
||||
// The collision flag indicates that the bucket is part of a collision chain
|
||||
// such that at least two entries both hash to this bucket. When true, we
|
||||
// may need to seek further along the chain to find the entry.
|
||||
static const uint32_t COLLISION = 0x80000000UL;
|
||||
|
||||
// The present flag indicates that the bucket contains an initialized entry value.
|
||||
static const uint32_t PRESENT = 0x40000000UL;
|
||||
|
||||
// Mask for 30 bits worth of the hash code that are stored within the bucket to
|
||||
// speed up lookups and rehashing by eliminating the need to recalculate the
|
||||
// hash code of the entry's key.
|
||||
static const uint32_t HASH_MASK = 0x3fffffffUL;
|
||||
|
||||
// Combined value that stores the collision and present flags as well as
|
||||
// a 30 bit hash code.
|
||||
uint32_t cookie;
|
||||
|
||||
// Storage for the entry begins here.
|
||||
char entry[0];
|
||||
};
|
||||
|
||||
BasicHashtableImpl(size_t entrySize, bool hasTrivialDestructor,
|
||||
size_t minimumInitialCapacity, float loadFactor);
|
||||
BasicHashtableImpl(const BasicHashtableImpl& other);
|
||||
virtual ~BasicHashtableImpl();
|
||||
|
||||
void dispose();
|
||||
|
||||
inline void edit() {
|
||||
if (mBuckets && !SharedBuffer::bufferFromData(mBuckets)->onlyOwner()) {
|
||||
clone();
|
||||
}
|
||||
}
|
||||
|
||||
void setTo(const BasicHashtableImpl& other);
|
||||
void clear();
|
||||
|
||||
ssize_t next(ssize_t index) const;
|
||||
ssize_t find(ssize_t index, hash_t hash, const void* __restrict__ key) const;
|
||||
size_t add(hash_t hash, const void* __restrict__ entry);
|
||||
void removeAt(size_t index);
|
||||
void rehash(size_t minimumCapacity, float loadFactor);
|
||||
|
||||
const size_t mBucketSize; // number of bytes per bucket including the entry
|
||||
const bool mHasTrivialDestructor; // true if the entry type does not require destruction
|
||||
size_t mCapacity; // number of buckets that can be filled before exceeding load factor
|
||||
float mLoadFactor; // load factor
|
||||
size_t mSize; // number of elements actually in the table
|
||||
size_t mFilledBuckets; // number of buckets for which collision or present is true
|
||||
size_t mBucketCount; // number of slots in the mBuckets array
|
||||
void* mBuckets; // array of buckets, as a SharedBuffer
|
||||
|
||||
inline const Bucket& bucketAt(const void* __restrict__ buckets, size_t index) const {
|
||||
return *reinterpret_cast<const Bucket*>(
|
||||
static_cast<const uint8_t*>(buckets) + index * mBucketSize);
|
||||
}
|
||||
|
||||
inline Bucket& bucketAt(void* __restrict__ buckets, size_t index) const {
|
||||
return *reinterpret_cast<Bucket*>(static_cast<uint8_t*>(buckets) + index * mBucketSize);
|
||||
}
|
||||
|
||||
virtual bool compareBucketKey(const Bucket& bucket, const void* __restrict__ key) const = 0;
|
||||
virtual void initializeBucketEntry(Bucket& bucket, const void* __restrict__ entry) const = 0;
|
||||
virtual void destroyBucketEntry(Bucket& bucket) const = 0;
|
||||
|
||||
private:
|
||||
void clone();
|
||||
|
||||
// Allocates a bucket array as a SharedBuffer.
|
||||
void* allocateBuckets(size_t count) const;
|
||||
|
||||
// Releases a bucket array's associated SharedBuffer.
|
||||
void releaseBuckets(void* __restrict__ buckets, size_t count) const;
|
||||
|
||||
// Destroys the contents of buckets (invokes destroyBucketEntry for each
|
||||
// populated bucket if needed).
|
||||
void destroyBuckets(void* __restrict__ buckets, size_t count) const;
|
||||
|
||||
// Copies the content of buckets (copies the cookie and invokes copyBucketEntry
|
||||
// for each populated bucket if needed).
|
||||
void copyBuckets(const void* __restrict__ fromBuckets,
|
||||
void* __restrict__ toBuckets, size_t count) const;
|
||||
|
||||
// Determines the appropriate size of a bucket array to store a certain minimum
|
||||
// number of entries and returns its effective capacity.
|
||||
static void determineCapacity(size_t minimumCapacity, float loadFactor,
|
||||
size_t* __restrict__ outBucketCount, size_t* __restrict__ outCapacity);
|
||||
|
||||
// Trim a hash code to 30 bits to match what we store in the bucket's cookie.
|
||||
inline static hash_t trimHash(hash_t hash) {
|
||||
return (hash & Bucket::HASH_MASK) ^ (hash >> 30);
|
||||
}
|
||||
|
||||
// Returns the index of the first bucket that is in the collision chain
|
||||
// for the specified hash code, given the total number of buckets.
|
||||
// (Primary hash)
|
||||
inline static size_t chainStart(hash_t hash, size_t count) {
|
||||
return hash % count;
|
||||
}
|
||||
|
||||
// Returns the increment to add to a bucket index to seek to the next bucket
|
||||
// in the collision chain for the specified hash code, given the total number of buckets.
|
||||
// (Secondary hash)
|
||||
inline static size_t chainIncrement(hash_t hash, size_t count) {
|
||||
return ((hash >> 7) | (hash << 25)) % (count - 1) + 1;
|
||||
}
|
||||
|
||||
// Returns the index of the next bucket that is in the collision chain
|
||||
// that is defined by the specified increment, given the total number of buckets.
|
||||
inline static size_t chainSeek(size_t index, size_t increment, size_t count) {
|
||||
return (index + increment) % count;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A BasicHashtable stores entries that are indexed by hash code in place
|
||||
* within an array. The basic operations are finding entries by key,
|
||||
* adding new entries and removing existing entries.
|
||||
*
|
||||
* This class provides a very limited set of operations with simple semantics.
|
||||
* It is intended to be used as a building block to construct more complex
|
||||
* and interesting data structures such as HashMap. Think very hard before
|
||||
* adding anything extra to BasicHashtable, it probably belongs at a
|
||||
* higher level of abstraction.
|
||||
*
|
||||
* TKey: The key type.
|
||||
* TEntry: The entry type which is what is actually stored in the array.
|
||||
*
|
||||
* TKey must support the following contract:
|
||||
* bool operator==(const TKey& other) const; // return true if equal
|
||||
* bool operator!=(const TKey& other) const; // return true if unequal
|
||||
*
|
||||
* TEntry must support the following contract:
|
||||
* const TKey& getKey() const; // get the key from the entry
|
||||
*
|
||||
* This class supports storing entries with duplicate keys. Of course, it can't
|
||||
* tell them apart during removal so only the first entry will be removed.
|
||||
* We do this because it means that operations like add() can't fail.
|
||||
*/
|
||||
template <typename TKey, typename TEntry>
|
||||
class BasicHashtable : private BasicHashtableImpl {
|
||||
public:
|
||||
/* Creates a hashtable with the specified minimum initial capacity.
|
||||
* The underlying array will be created when the first entry is added.
|
||||
*
|
||||
* minimumInitialCapacity: The minimum initial capacity for the hashtable.
|
||||
* Default is 0.
|
||||
* loadFactor: The desired load factor for the hashtable, between 0 and 1.
|
||||
* Default is 0.75.
|
||||
*/
|
||||
BasicHashtable(size_t minimumInitialCapacity = 0, float loadFactor = 0.75f);
|
||||
|
||||
/* Copies a hashtable.
|
||||
* The underlying storage is shared copy-on-write.
|
||||
*/
|
||||
BasicHashtable(const BasicHashtable& other);
|
||||
|
||||
/* Clears and destroys the hashtable.
|
||||
*/
|
||||
virtual ~BasicHashtable();
|
||||
|
||||
/* Making this hashtable a copy of the other hashtable.
|
||||
* The underlying storage is shared copy-on-write.
|
||||
*
|
||||
* other: The hashtable to copy.
|
||||
*/
|
||||
inline BasicHashtable<TKey, TEntry>& operator =(const BasicHashtable<TKey, TEntry> & other) {
|
||||
setTo(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Returns the number of entries in the hashtable.
|
||||
*/
|
||||
inline size_t size() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
/* Returns the capacity of the hashtable, which is the number of elements that can
|
||||
* added to the hashtable without requiring it to be grown.
|
||||
*/
|
||||
inline size_t capacity() const {
|
||||
return mCapacity;
|
||||
}
|
||||
|
||||
/* Returns the number of buckets that the hashtable has, which is the size of its
|
||||
* underlying array.
|
||||
*/
|
||||
inline size_t bucketCount() const {
|
||||
return mBucketCount;
|
||||
}
|
||||
|
||||
/* Returns the load factor of the hashtable. */
|
||||
inline float loadFactor() const {
|
||||
return mLoadFactor;
|
||||
};
|
||||
|
||||
/* Returns a const reference to the entry at the specified index.
|
||||
*
|
||||
* index: The index of the entry to retrieve. Must be a valid index within
|
||||
* the bounds of the hashtable.
|
||||
*/
|
||||
inline const TEntry& entryAt(size_t index) const {
|
||||
return entryFor(bucketAt(mBuckets, index));
|
||||
}
|
||||
|
||||
/* Returns a non-const reference to the entry at the specified index.
|
||||
*
|
||||
* index: The index of the entry to edit. Must be a valid index within
|
||||
* the bounds of the hashtable.
|
||||
*/
|
||||
inline TEntry& editEntryAt(size_t index) {
|
||||
edit();
|
||||
return entryFor(bucketAt(mBuckets, index));
|
||||
}
|
||||
|
||||
/* Clears the hashtable.
|
||||
* All entries in the hashtable are destroyed immediately.
|
||||
* If you need to do something special with the entries in the hashtable then iterate
|
||||
* over them and do what you need before clearing the hashtable.
|
||||
*/
|
||||
inline void clear() {
|
||||
BasicHashtableImpl::clear();
|
||||
}
|
||||
|
||||
/* Returns the index of the next entry in the hashtable given the index of a previous entry.
|
||||
* If the given index is -1, then returns the index of the first entry in the hashtable,
|
||||
* if there is one, or -1 otherwise.
|
||||
* If the given index is not -1, then returns the index of the next entry in the hashtable,
|
||||
* in strictly increasing order, or -1 if there are none left.
|
||||
*
|
||||
* index: The index of the previous entry that was iterated, or -1 to begin
|
||||
* iteration at the beginning of the hashtable.
|
||||
*/
|
||||
inline ssize_t next(ssize_t index) const {
|
||||
return BasicHashtableImpl::next(index);
|
||||
}
|
||||
|
||||
/* Finds the index of an entry with the specified key.
|
||||
* If the given index is -1, then returns the index of the first matching entry,
|
||||
* otherwise returns the index of the next matching entry.
|
||||
* If the hashtable contains multiple entries with keys that match the requested
|
||||
* key, then the sequence of entries returned is arbitrary.
|
||||
* Returns -1 if no entry was found.
|
||||
*
|
||||
* index: The index of the previous entry with the specified key, or -1 to
|
||||
* find the first matching entry.
|
||||
* hash: The hashcode of the key.
|
||||
* key: The key.
|
||||
*/
|
||||
inline ssize_t find(ssize_t index, hash_t hash, const TKey& key) const {
|
||||
return BasicHashtableImpl::find(index, hash, &key);
|
||||
}
|
||||
|
||||
/* Adds the entry to the hashtable.
|
||||
* Returns the index of the newly added entry.
|
||||
* If an entry with the same key already exists, then a duplicate entry is added.
|
||||
* If the entry will not fit, then the hashtable's capacity is increased and
|
||||
* its contents are rehashed. See rehash().
|
||||
*
|
||||
* hash: The hashcode of the key.
|
||||
* entry: The entry to add.
|
||||
*/
|
||||
inline size_t add(hash_t hash, const TEntry& entry) {
|
||||
return BasicHashtableImpl::add(hash, &entry);
|
||||
}
|
||||
|
||||
/* Removes the entry with the specified index from the hashtable.
|
||||
* The entry is destroyed immediately.
|
||||
* The index must be valid.
|
||||
*
|
||||
* The hashtable is not compacted after an item is removed, so it is legal
|
||||
* to continue iterating over the hashtable using next() or find().
|
||||
*
|
||||
* index: The index of the entry to remove. Must be a valid index within the
|
||||
* bounds of the hashtable, and it must refer to an existing entry.
|
||||
*/
|
||||
inline void removeAt(size_t index) {
|
||||
BasicHashtableImpl::removeAt(index);
|
||||
}
|
||||
|
||||
/* Rehashes the contents of the hashtable.
|
||||
* Grows the hashtable to at least the specified minimum capacity or the
|
||||
* current number of elements, whichever is larger.
|
||||
*
|
||||
* Rehashing causes all entries to be copied and the entry indices may change.
|
||||
* Although the hash codes are cached by the hashtable, rehashing can be an
|
||||
* expensive operation and should be avoided unless the hashtable's size
|
||||
* needs to be changed.
|
||||
*
|
||||
* Rehashing is the only way to change the capacity or load factor of the
|
||||
* hashtable once it has been created. It can be used to compact the
|
||||
* hashtable by choosing a minimum capacity that is smaller than the current
|
||||
* capacity (such as 0).
|
||||
*
|
||||
* minimumCapacity: The desired minimum capacity after rehashing.
|
||||
* loadFactor: The desired load factor after rehashing.
|
||||
*/
|
||||
inline void rehash(size_t minimumCapacity, float loadFactor) {
|
||||
BasicHashtableImpl::rehash(minimumCapacity, loadFactor);
|
||||
}
|
||||
|
||||
/* Determines whether there is room to add another entry without rehashing.
|
||||
* When this returns true, a subsequent add() operation is guaranteed to
|
||||
* complete without performing a rehash.
|
||||
*/
|
||||
inline bool hasMoreRoom() const {
|
||||
return mCapacity > mFilledBuckets;
|
||||
}
|
||||
|
||||
protected:
|
||||
static inline const TEntry& entryFor(const Bucket& bucket) {
|
||||
return reinterpret_cast<const TEntry&>(bucket.entry);
|
||||
}
|
||||
|
||||
static inline TEntry& entryFor(Bucket& bucket) {
|
||||
return reinterpret_cast<TEntry&>(bucket.entry);
|
||||
}
|
||||
|
||||
virtual bool compareBucketKey(const Bucket& bucket, const void* __restrict__ key) const;
|
||||
virtual void initializeBucketEntry(Bucket& bucket, const void* __restrict__ entry) const;
|
||||
virtual void destroyBucketEntry(Bucket& bucket) const;
|
||||
|
||||
private:
|
||||
// For dumping the raw contents of a hashtable during testing.
|
||||
friend class BasicHashtableTest;
|
||||
inline uint32_t cookieAt(size_t index) const {
|
||||
return bucketAt(mBuckets, index).cookie;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TKey, typename TEntry>
|
||||
BasicHashtable<TKey, TEntry>::BasicHashtable(size_t minimumInitialCapacity, float loadFactor) :
|
||||
BasicHashtableImpl(sizeof(TEntry), traits<TEntry>::has_trivial_dtor,
|
||||
minimumInitialCapacity, loadFactor) {
|
||||
}
|
||||
|
||||
template <typename TKey, typename TEntry>
|
||||
BasicHashtable<TKey, TEntry>::BasicHashtable(const BasicHashtable<TKey, TEntry>& other) :
|
||||
BasicHashtableImpl(other) {
|
||||
}
|
||||
|
||||
template <typename TKey, typename TEntry>
|
||||
BasicHashtable<TKey, TEntry>::~BasicHashtable() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
template <typename TKey, typename TEntry>
|
||||
bool BasicHashtable<TKey, TEntry>::compareBucketKey(const Bucket& bucket,
|
||||
const void* __restrict__ key) const {
|
||||
return entryFor(bucket).getKey() == *static_cast<const TKey*>(key);
|
||||
}
|
||||
|
||||
template <typename TKey, typename TEntry>
|
||||
void BasicHashtable<TKey, TEntry>::initializeBucketEntry(Bucket& bucket,
|
||||
const void* __restrict__ entry) const {
|
||||
if (!traits<TEntry>::has_trivial_copy) {
|
||||
new (&entryFor(bucket)) TEntry(*(static_cast<const TEntry*>(entry)));
|
||||
} else {
|
||||
memcpy(&entryFor(bucket), entry, sizeof(TEntry));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TKey, typename TEntry>
|
||||
void BasicHashtable<TKey, TEntry>::destroyBucketEntry(Bucket& bucket) const {
|
||||
if (!traits<TEntry>::has_trivial_dtor) {
|
||||
entryFor(bucket).~TEntry();
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_BASIC_HASHTABLE_H
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 UTILS_BITSET_H
|
||||
#define UTILS_BITSET_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <utils/TypeHelpers.h>
|
||||
|
||||
/*
|
||||
* Contains some bit manipulation helpers.
|
||||
*/
|
||||
|
||||
namespace android {
|
||||
|
||||
// A simple set of 32 bits that can be individually marked or cleared.
|
||||
struct BitSet32 {
|
||||
uint32_t value;
|
||||
|
||||
inline BitSet32() : value(0UL) { }
|
||||
explicit inline BitSet32(uint32_t value) : value(value) { }
|
||||
|
||||
// Gets the value associated with a particular bit index.
|
||||
static inline uint32_t valueForBit(uint32_t n) { return 0x80000000UL >> n; }
|
||||
|
||||
// Clears the bit set.
|
||||
inline void clear() { clear(value); }
|
||||
|
||||
static inline void clear(uint32_t& value) { value = 0UL; }
|
||||
|
||||
// Returns the number of marked bits in the set.
|
||||
inline uint32_t count() const { return count(value); }
|
||||
|
||||
static inline uint32_t count(uint32_t value) { return __builtin_popcountl(value); }
|
||||
|
||||
// Returns true if the bit set does not contain any marked bits.
|
||||
inline bool isEmpty() const { return isEmpty(value); }
|
||||
|
||||
static inline bool isEmpty(uint32_t value) { return ! value; }
|
||||
|
||||
// Returns true if the bit set does not contain any unmarked bits.
|
||||
inline bool isFull() const { return isFull(value); }
|
||||
|
||||
static inline bool isFull(uint32_t value) { return value == 0xffffffffUL; }
|
||||
|
||||
// Returns true if the specified bit is marked.
|
||||
inline bool hasBit(uint32_t n) const { return hasBit(value, n); }
|
||||
|
||||
static inline bool hasBit(uint32_t value, uint32_t n) { return value & valueForBit(n); }
|
||||
|
||||
// Marks the specified bit.
|
||||
inline void markBit(uint32_t n) { markBit(value, n); }
|
||||
|
||||
static inline void markBit (uint32_t& value, uint32_t n) { value |= valueForBit(n); }
|
||||
|
||||
// Clears the specified bit.
|
||||
inline void clearBit(uint32_t n) { clearBit(value, n); }
|
||||
|
||||
static inline void clearBit(uint32_t& value, uint32_t n) { value &= ~ valueForBit(n); }
|
||||
|
||||
// Finds the first marked bit in the set.
|
||||
// Result is undefined if all bits are unmarked.
|
||||
inline uint32_t firstMarkedBit() const { return firstMarkedBit(value); }
|
||||
|
||||
static uint32_t firstMarkedBit(uint32_t value) { return clz_checked(value); }
|
||||
|
||||
// Finds the first unmarked bit in the set.
|
||||
// Result is undefined if all bits are marked.
|
||||
inline uint32_t firstUnmarkedBit() const { return firstUnmarkedBit(value); }
|
||||
|
||||
static inline uint32_t firstUnmarkedBit(uint32_t value) { return clz_checked(~ value); }
|
||||
|
||||
// Finds the last marked bit in the set.
|
||||
// Result is undefined if all bits are unmarked.
|
||||
inline uint32_t lastMarkedBit() const { return lastMarkedBit(value); }
|
||||
|
||||
static inline uint32_t lastMarkedBit(uint32_t value) { return 31 - ctz_checked(value); }
|
||||
|
||||
// Finds the first marked bit in the set and clears it. Returns the bit index.
|
||||
// Result is undefined if all bits are unmarked.
|
||||
inline uint32_t clearFirstMarkedBit() { return clearFirstMarkedBit(value); }
|
||||
|
||||
static inline uint32_t clearFirstMarkedBit(uint32_t& value) {
|
||||
uint32_t n = firstMarkedBit(value);
|
||||
clearBit(value, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Finds the first unmarked bit in the set and marks it. Returns the bit index.
|
||||
// Result is undefined if all bits are marked.
|
||||
inline uint32_t markFirstUnmarkedBit() { return markFirstUnmarkedBit(value); }
|
||||
|
||||
static inline uint32_t markFirstUnmarkedBit(uint32_t& value) {
|
||||
uint32_t n = firstUnmarkedBit(value);
|
||||
markBit(value, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Finds the last marked bit in the set and clears it. Returns the bit index.
|
||||
// Result is undefined if all bits are unmarked.
|
||||
inline uint32_t clearLastMarkedBit() { return clearLastMarkedBit(value); }
|
||||
|
||||
static inline uint32_t clearLastMarkedBit(uint32_t& value) {
|
||||
uint32_t n = lastMarkedBit(value);
|
||||
clearBit(value, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Gets the index of the specified bit in the set, which is the number of
|
||||
// marked bits that appear before the specified bit.
|
||||
inline uint32_t getIndexOfBit(uint32_t n) const {
|
||||
return getIndexOfBit(value, n);
|
||||
}
|
||||
|
||||
static inline uint32_t getIndexOfBit(uint32_t value, uint32_t n) {
|
||||
return __builtin_popcountl(value & ~(0xffffffffUL >> n));
|
||||
}
|
||||
|
||||
inline bool operator== (const BitSet32& other) const { return value == other.value; }
|
||||
inline bool operator!= (const BitSet32& other) const { return value != other.value; }
|
||||
inline BitSet32 operator& (const BitSet32& other) const {
|
||||
return BitSet32(value & other.value);
|
||||
}
|
||||
inline BitSet32& operator&= (const BitSet32& other) {
|
||||
value &= other.value;
|
||||
return *this;
|
||||
}
|
||||
inline BitSet32 operator| (const BitSet32& other) const {
|
||||
return BitSet32(value | other.value);
|
||||
}
|
||||
inline BitSet32& operator|= (const BitSet32& other) {
|
||||
value |= other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
// We use these helpers as the signature of __builtin_c{l,t}z has "unsigned int" for the
|
||||
// input, which is only guaranteed to be 16b, not 32. The compiler should optimize this away.
|
||||
static inline uint32_t clz_checked(uint32_t value) {
|
||||
if (sizeof(unsigned int) == sizeof(uint32_t)) {
|
||||
return __builtin_clz(value);
|
||||
} else {
|
||||
return __builtin_clzl(value);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t ctz_checked(uint32_t value) {
|
||||
if (sizeof(unsigned int) == sizeof(uint32_t)) {
|
||||
return __builtin_ctz(value);
|
||||
} else {
|
||||
return __builtin_ctzl(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ANDROID_BASIC_TYPES_TRAITS(BitSet32)
|
||||
|
||||
// A simple set of 64 bits that can be individually marked or cleared.
|
||||
struct BitSet64 {
|
||||
uint64_t value;
|
||||
|
||||
inline BitSet64() : value(0ULL) { }
|
||||
explicit inline BitSet64(uint64_t value) : value(value) { }
|
||||
|
||||
// Gets the value associated with a particular bit index.
|
||||
static inline uint64_t valueForBit(uint32_t n) { return 0x8000000000000000ULL >> n; }
|
||||
|
||||
// Clears the bit set.
|
||||
inline void clear() { clear(value); }
|
||||
|
||||
static inline void clear(uint64_t& value) { value = 0ULL; }
|
||||
|
||||
// Returns the number of marked bits in the set.
|
||||
inline uint32_t count() const { return count(value); }
|
||||
|
||||
static inline uint32_t count(uint64_t value) { return __builtin_popcountll(value); }
|
||||
|
||||
// Returns true if the bit set does not contain any marked bits.
|
||||
inline bool isEmpty() const { return isEmpty(value); }
|
||||
|
||||
static inline bool isEmpty(uint64_t value) { return ! value; }
|
||||
|
||||
// Returns true if the bit set does not contain any unmarked bits.
|
||||
inline bool isFull() const { return isFull(value); }
|
||||
|
||||
static inline bool isFull(uint64_t value) { return value == 0xffffffffffffffffULL; }
|
||||
|
||||
// Returns true if the specified bit is marked.
|
||||
inline bool hasBit(uint32_t n) const { return hasBit(value, n); }
|
||||
|
||||
static inline bool hasBit(uint64_t value, uint32_t n) { return value & valueForBit(n); }
|
||||
|
||||
// Marks the specified bit.
|
||||
inline void markBit(uint32_t n) { markBit(value, n); }
|
||||
|
||||
static inline void markBit(uint64_t& value, uint32_t n) { value |= valueForBit(n); }
|
||||
|
||||
// Clears the specified bit.
|
||||
inline void clearBit(uint32_t n) { clearBit(value, n); }
|
||||
|
||||
static inline void clearBit(uint64_t& value, uint32_t n) { value &= ~ valueForBit(n); }
|
||||
|
||||
// Finds the first marked bit in the set.
|
||||
// Result is undefined if all bits are unmarked.
|
||||
inline uint32_t firstMarkedBit() const { return firstMarkedBit(value); }
|
||||
|
||||
static inline uint32_t firstMarkedBit(uint64_t value) { return __builtin_clzll(value); }
|
||||
|
||||
// Finds the first unmarked bit in the set.
|
||||
// Result is undefined if all bits are marked.
|
||||
inline uint32_t firstUnmarkedBit() const { return firstUnmarkedBit(value); }
|
||||
|
||||
static inline uint32_t firstUnmarkedBit(uint64_t value) { return __builtin_clzll(~ value); }
|
||||
|
||||
// Finds the last marked bit in the set.
|
||||
// Result is undefined if all bits are unmarked.
|
||||
inline uint32_t lastMarkedBit() const { return lastMarkedBit(value); }
|
||||
|
||||
static inline uint32_t lastMarkedBit(uint64_t value) { return 63 - __builtin_ctzll(value); }
|
||||
|
||||
// Finds the first marked bit in the set and clears it. Returns the bit index.
|
||||
// Result is undefined if all bits are unmarked.
|
||||
inline uint32_t clearFirstMarkedBit() { return clearFirstMarkedBit(value); }
|
||||
|
||||
static inline uint32_t clearFirstMarkedBit(uint64_t& value) {
|
||||
uint64_t n = firstMarkedBit(value);
|
||||
clearBit(value, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Finds the first unmarked bit in the set and marks it. Returns the bit index.
|
||||
// Result is undefined if all bits are marked.
|
||||
inline uint32_t markFirstUnmarkedBit() { return markFirstUnmarkedBit(value); }
|
||||
|
||||
static inline uint32_t markFirstUnmarkedBit(uint64_t& value) {
|
||||
uint64_t n = firstUnmarkedBit(value);
|
||||
markBit(value, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Finds the last marked bit in the set and clears it. Returns the bit index.
|
||||
// Result is undefined if all bits are unmarked.
|
||||
inline uint32_t clearLastMarkedBit() { return clearLastMarkedBit(value); }
|
||||
|
||||
static inline uint32_t clearLastMarkedBit(uint64_t& value) {
|
||||
uint64_t n = lastMarkedBit(value);
|
||||
clearBit(value, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Gets the index of the specified bit in the set, which is the number of
|
||||
// marked bits that appear before the specified bit.
|
||||
inline uint32_t getIndexOfBit(uint32_t n) const { return getIndexOfBit(value, n); }
|
||||
|
||||
static inline uint32_t getIndexOfBit(uint64_t value, uint32_t n) {
|
||||
return __builtin_popcountll(value & ~(0xffffffffffffffffULL >> n));
|
||||
}
|
||||
|
||||
inline bool operator== (const BitSet64& other) const { return value == other.value; }
|
||||
inline bool operator!= (const BitSet64& other) const { return value != other.value; }
|
||||
inline BitSet64 operator& (const BitSet64& other) const {
|
||||
return BitSet64(value & other.value);
|
||||
}
|
||||
inline BitSet64& operator&= (const BitSet64& other) {
|
||||
value &= other.value;
|
||||
return *this;
|
||||
}
|
||||
inline BitSet64 operator| (const BitSet64& other) const {
|
||||
return BitSet64(value | other.value);
|
||||
}
|
||||
inline BitSet64& operator|= (const BitSet64& other) {
|
||||
value |= other.value;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
ANDROID_BASIC_TYPES_TRAITS(BitSet64)
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // UTILS_BITSET_H
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
** Copyright 2011, 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_BLOB_CACHE_H
|
||||
#define ANDROID_BLOB_CACHE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <utils/Flattenable.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/SortedVector.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// A BlobCache is an in-memory cache for binary key/value pairs. A BlobCache
|
||||
// does NOT provide any thread-safety guarantees.
|
||||
//
|
||||
// The cache contents can be serialized to an in-memory buffer or mmap'd file
|
||||
// and then reloaded in a subsequent execution of the program. This
|
||||
// serialization is non-portable and the data should only be used by the device
|
||||
// that generated it.
|
||||
class BlobCache : public RefBase {
|
||||
|
||||
public:
|
||||
|
||||
// Create an empty blob cache. The blob cache will cache key/value pairs
|
||||
// with key and value sizes less than or equal to maxKeySize and
|
||||
// maxValueSize, respectively. The total combined size of ALL cache entries
|
||||
// (key sizes plus value sizes) will not exceed maxTotalSize.
|
||||
BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize);
|
||||
|
||||
// set inserts a new binary value into the cache and associates it with the
|
||||
// given binary key. If the key or value are too large for the cache then
|
||||
// the cache remains unchanged. This includes the case where a different
|
||||
// value was previously associated with the given key - the old value will
|
||||
// remain in the cache. If the given key and value are small enough to be
|
||||
// put in the cache (based on the maxKeySize, maxValueSize, and maxTotalSize
|
||||
// values specified to the BlobCache constructor), then the key/value pair
|
||||
// will be in the cache after set returns. Note, however, that a subsequent
|
||||
// call to set may evict old key/value pairs from the cache.
|
||||
//
|
||||
// Preconditions:
|
||||
// key != NULL
|
||||
// 0 < keySize
|
||||
// value != NULL
|
||||
// 0 < valueSize
|
||||
void set(const void* key, size_t keySize, const void* value,
|
||||
size_t valueSize);
|
||||
|
||||
// get retrieves from the cache the binary value associated with a given
|
||||
// binary key. If the key is present in the cache then the length of the
|
||||
// binary value associated with that key is returned. If the value argument
|
||||
// is non-NULL and the size of the cached value is less than valueSize bytes
|
||||
// then the cached value is copied into the buffer pointed to by the value
|
||||
// argument. If the key is not present in the cache then 0 is returned and
|
||||
// the buffer pointed to by the value argument is not modified.
|
||||
//
|
||||
// Note that when calling get multiple times with the same key, the later
|
||||
// calls may fail, returning 0, even if earlier calls succeeded. The return
|
||||
// value must be checked for each call.
|
||||
//
|
||||
// Preconditions:
|
||||
// key != NULL
|
||||
// 0 < keySize
|
||||
// 0 <= valueSize
|
||||
size_t get(const void* key, size_t keySize, void* value, size_t valueSize);
|
||||
|
||||
|
||||
// getFlattenedSize returns the number of bytes needed to store the entire
|
||||
// serialized cache.
|
||||
size_t getFlattenedSize() const;
|
||||
|
||||
// flatten serializes the current contents of the cache into the memory
|
||||
// pointed to by 'buffer'. The serialized cache contents can later be
|
||||
// loaded into a BlobCache object using the unflatten method. The contents
|
||||
// of the BlobCache object will not be modified.
|
||||
//
|
||||
// Preconditions:
|
||||
// size >= this.getFlattenedSize()
|
||||
status_t flatten(void* buffer, size_t size) const;
|
||||
|
||||
// unflatten replaces the contents of the cache with the serialized cache
|
||||
// contents in the memory pointed to by 'buffer'. The previous contents of
|
||||
// the BlobCache will be evicted from the cache. If an error occurs while
|
||||
// unflattening the serialized cache contents then the BlobCache will be
|
||||
// left in an empty state.
|
||||
//
|
||||
status_t unflatten(void const* buffer, size_t size);
|
||||
|
||||
private:
|
||||
// Copying is disallowed.
|
||||
BlobCache(const BlobCache&);
|
||||
void operator=(const BlobCache&);
|
||||
|
||||
// A random function helper to get around MinGW not having nrand48()
|
||||
long int blob_random();
|
||||
|
||||
// clean evicts a randomly chosen set of entries from the cache such that
|
||||
// the total size of all remaining entries is less than mMaxTotalSize/2.
|
||||
void clean();
|
||||
|
||||
// isCleanable returns true if the cache is full enough for the clean method
|
||||
// to have some effect, and false otherwise.
|
||||
bool isCleanable() const;
|
||||
|
||||
// A Blob is an immutable sized unstructured data blob.
|
||||
class Blob : public RefBase {
|
||||
public:
|
||||
Blob(const void* data, size_t size, bool copyData);
|
||||
~Blob();
|
||||
|
||||
bool operator<(const Blob& rhs) const;
|
||||
|
||||
const void* getData() const;
|
||||
size_t getSize() const;
|
||||
|
||||
private:
|
||||
// Copying is not allowed.
|
||||
Blob(const Blob&);
|
||||
void operator=(const Blob&);
|
||||
|
||||
// mData points to the buffer containing the blob data.
|
||||
const void* mData;
|
||||
|
||||
// mSize is the size of the blob data in bytes.
|
||||
size_t mSize;
|
||||
|
||||
// mOwnsData indicates whether or not this Blob object should free the
|
||||
// memory pointed to by mData when the Blob gets destructed.
|
||||
bool mOwnsData;
|
||||
};
|
||||
|
||||
// A CacheEntry is a single key/value pair in the cache.
|
||||
class CacheEntry {
|
||||
public:
|
||||
CacheEntry();
|
||||
CacheEntry(const sp<Blob>& key, const sp<Blob>& value);
|
||||
CacheEntry(const CacheEntry& ce);
|
||||
|
||||
bool operator<(const CacheEntry& rhs) const;
|
||||
const CacheEntry& operator=(const CacheEntry&);
|
||||
|
||||
sp<Blob> getKey() const;
|
||||
sp<Blob> getValue() const;
|
||||
|
||||
void setValue(const sp<Blob>& value);
|
||||
|
||||
private:
|
||||
|
||||
// mKey is the key that identifies the cache entry.
|
||||
sp<Blob> mKey;
|
||||
|
||||
// mValue is the cached data associated with the key.
|
||||
sp<Blob> mValue;
|
||||
};
|
||||
|
||||
// A Header is the header for the entire BlobCache serialization format. No
|
||||
// need to make this portable, so we simply write the struct out.
|
||||
struct Header {
|
||||
// mMagicNumber is the magic number that identifies the data as
|
||||
// serialized BlobCache contents. It must always contain 'Blb$'.
|
||||
uint32_t mMagicNumber;
|
||||
|
||||
// mBlobCacheVersion is the serialization format version.
|
||||
uint32_t mBlobCacheVersion;
|
||||
|
||||
// mDeviceVersion is the device-specific version of the cache. This can
|
||||
// be used to invalidate the cache.
|
||||
uint32_t mDeviceVersion;
|
||||
|
||||
// mNumEntries is number of cache entries following the header in the
|
||||
// data.
|
||||
size_t mNumEntries;
|
||||
|
||||
// mBuildId is the build id of the device when the cache was created.
|
||||
// When an update to the build happens (via an OTA or other update) this
|
||||
// is used to invalidate the cache.
|
||||
int mBuildIdLength;
|
||||
char mBuildId[];
|
||||
};
|
||||
|
||||
// An EntryHeader is the header for a serialized cache entry. No need to
|
||||
// make this portable, so we simply write the struct out. Each EntryHeader
|
||||
// is followed imediately by the key data and then the value data.
|
||||
//
|
||||
// The beginning of each serialized EntryHeader is 4-byte aligned, so the
|
||||
// number of bytes that a serialized cache entry will occupy is:
|
||||
//
|
||||
// ((sizeof(EntryHeader) + keySize + valueSize) + 3) & ~3
|
||||
//
|
||||
struct EntryHeader {
|
||||
// mKeySize is the size of the entry key in bytes.
|
||||
size_t mKeySize;
|
||||
|
||||
// mValueSize is the size of the entry value in bytes.
|
||||
size_t mValueSize;
|
||||
|
||||
// mData contains both the key and value data for the cache entry. The
|
||||
// key comes first followed immediately by the value.
|
||||
uint8_t mData[];
|
||||
};
|
||||
|
||||
// mMaxKeySize is the maximum key size that will be cached. Calls to
|
||||
// BlobCache::set with a keySize parameter larger than mMaxKeySize will
|
||||
// simply not add the key/value pair to the cache.
|
||||
const size_t mMaxKeySize;
|
||||
|
||||
// mMaxValueSize is the maximum value size that will be cached. Calls to
|
||||
// BlobCache::set with a valueSize parameter larger than mMaxValueSize will
|
||||
// simply not add the key/value pair to the cache.
|
||||
const size_t mMaxValueSize;
|
||||
|
||||
// mMaxTotalSize is the maximum size that all cache entries can occupy. This
|
||||
// includes space for both keys and values. When a call to BlobCache::set
|
||||
// would otherwise cause this limit to be exceeded, either the key/value
|
||||
// pair passed to BlobCache::set will not be cached or other cache entries
|
||||
// will be evicted from the cache to make room for the new entry.
|
||||
const size_t mMaxTotalSize;
|
||||
|
||||
// mTotalSize is the total combined size of all keys and values currently in
|
||||
// the cache.
|
||||
size_t mTotalSize;
|
||||
|
||||
// mRandState is the pseudo-random number generator state. It is passed to
|
||||
// nrand48 to generate random numbers when needed.
|
||||
unsigned short mRandState[3];
|
||||
|
||||
// mCacheEntries stores all the cache entries that are resident in memory.
|
||||
// Cache entries are added to it by the 'set' method.
|
||||
SortedVector<CacheEntry> mCacheEntries;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ANDROID_BLOB_CACHE_H
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 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 _LIBS_UTILS_BYTE_ORDER_H
|
||||
#define _LIBS_UTILS_BYTE_ORDER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_WINSOCK
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These macros are like the hton/ntoh byte swapping macros,
|
||||
* except they allow you to swap to and from the "device" byte
|
||||
* order. The device byte order is the endianness of the target
|
||||
* device -- for the ARM CPUs we use today, this is little endian.
|
||||
*
|
||||
* Note that the byte swapping functions have not been optimized
|
||||
* much; performance is currently not an issue for them since the
|
||||
* intent is to allow us to avoid byte swapping on the device.
|
||||
*/
|
||||
|
||||
static inline uint32_t android_swap_long(uint32_t v)
|
||||
{
|
||||
return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
|
||||
}
|
||||
|
||||
static inline uint16_t android_swap_short(uint16_t v)
|
||||
{
|
||||
return (v<<8) | (v>>8);
|
||||
}
|
||||
|
||||
#define DEVICE_BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
#if BYTE_ORDER == DEVICE_BYTE_ORDER
|
||||
|
||||
#define dtohl(x) (x)
|
||||
#define dtohs(x) (x)
|
||||
#define htodl(x) (x)
|
||||
#define htods(x) (x)
|
||||
|
||||
#else
|
||||
|
||||
#define dtohl(x) (android_swap_long(x))
|
||||
#define dtohs(x) (android_swap_short(x))
|
||||
#define htodl(x) (android_swap_long(x))
|
||||
#define htods(x) (android_swap_short(x))
|
||||
|
||||
#endif
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define fromlel(x) (x)
|
||||
#define fromles(x) (x)
|
||||
#define tolel(x) (x)
|
||||
#define toles(x) (x)
|
||||
#else
|
||||
#define fromlel(x) (android_swap_long(x))
|
||||
#define fromles(x) (android_swap_short(x))
|
||||
#define tolel(x) (android_swap_long(x))
|
||||
#define toles(x) (android_swap_short(x))
|
||||
#endif
|
||||
|
||||
#endif // _LIBS_UTILS_BYTE_ORDER_H
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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_CALLSTACK_H
|
||||
#define ANDROID_CALLSTACK_H
|
||||
|
||||
#include <android/log.h>
|
||||
#include <backtrace/backtrace_constants.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/Vector.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class Printer;
|
||||
|
||||
// Collect/print the call stack (function, file, line) traces for a single thread.
|
||||
class CallStack {
|
||||
public:
|
||||
// Create an empty call stack. No-op.
|
||||
CallStack();
|
||||
// Create a callstack with the current thread's stack trace.
|
||||
// Immediately dump it to logcat using the given logtag.
|
||||
CallStack(const char* logtag, int32_t ignoreDepth=1);
|
||||
~CallStack();
|
||||
|
||||
// Reset the stack frames (same as creating an empty call stack).
|
||||
void clear() { mFrameLines.clear(); }
|
||||
|
||||
// Immediately collect the stack traces for the specified thread.
|
||||
// The default is to dump the stack of the current call.
|
||||
void update(int32_t ignoreDepth=1, pid_t tid=BACKTRACE_CURRENT_THREAD);
|
||||
|
||||
// Dump a stack trace to the log using the supplied logtag.
|
||||
void log(const char* logtag,
|
||||
android_LogPriority priority = ANDROID_LOG_DEBUG,
|
||||
const char* prefix = 0) const;
|
||||
|
||||
// Dump a stack trace to the specified file descriptor.
|
||||
void dump(int fd, int indent = 0, const char* prefix = 0) const;
|
||||
|
||||
// Return a string (possibly very long) containing the complete stack trace.
|
||||
String8 toString(const char* prefix = 0) const;
|
||||
|
||||
// Dump a serialized representation of the stack trace to the specified printer.
|
||||
void print(Printer& printer) const;
|
||||
|
||||
// Get the count of stack frames that are in this call stack.
|
||||
size_t size() const { return mFrameLines.size(); }
|
||||
|
||||
private:
|
||||
Vector<String8> mFrameLines;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_CALLSTACK_H
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 __LIB_UTILS_COMPAT_H
|
||||
#define __LIB_UTILS_COMPAT_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
/* Mac OS has always had a 64-bit off_t, so it doesn't have off64_t. */
|
||||
|
||||
typedef off_t off64_t;
|
||||
|
||||
static inline off64_t lseek64(int fd, off64_t offset, int whence) {
|
||||
return lseek(fd, offset, whence);
|
||||
}
|
||||
|
||||
static inline ssize_t pread64(int fd, void* buf, size_t nbytes, off64_t offset) {
|
||||
return pread(fd, buf, nbytes, offset);
|
||||
}
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define O_CLOEXEC O_NOINHERIT
|
||||
#define O_NOFOLLOW 0
|
||||
#define DEFFILEMODE 0666
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define ZD "%ld"
|
||||
#define ZD_TYPE long
|
||||
#else
|
||||
#define ZD "%zd"
|
||||
#define ZD_TYPE ssize_t
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Needed for cases where something should be constexpr if possible, but not
|
||||
* being constexpr is fine if in pre-C++11 code (such as a const static float
|
||||
* member variable).
|
||||
*/
|
||||
#if __cplusplus >= 201103L
|
||||
#define CONSTEXPR constexpr
|
||||
#else
|
||||
#define CONSTEXPR
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TEMP_FAILURE_RETRY is defined by some, but not all, versions of
|
||||
* <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
|
||||
* not already defined, then define it here.
|
||||
*/
|
||||
#ifndef TEMP_FAILURE_RETRY
|
||||
/* Used to retry syscalls that can return EINTR. */
|
||||
#define TEMP_FAILURE_RETRY(exp) ({ \
|
||||
typeof (exp) _rc; \
|
||||
do { \
|
||||
_rc = (exp); \
|
||||
} while (_rc == -1 && errno == EINTR); \
|
||||
_rc; })
|
||||
#endif
|
||||
|
||||
#endif /* __LIB_UTILS_COMPAT_H */
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 _LIBS_UTILS_CONDITION_H
|
||||
#define _LIBS_UTILS_CONDITION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Condition variable class. The implementation is system-dependent.
|
||||
*
|
||||
* Condition variables are paired up with mutexes. Lock the mutex,
|
||||
* call wait(), then either re-wait() if things aren't quite what you want,
|
||||
* or unlock the mutex and continue. All threads calling wait() must
|
||||
* use the same mutex for a given Condition.
|
||||
*/
|
||||
class Condition {
|
||||
public:
|
||||
enum {
|
||||
PRIVATE = 0,
|
||||
SHARED = 1
|
||||
};
|
||||
|
||||
enum WakeUpType {
|
||||
WAKE_UP_ONE = 0,
|
||||
WAKE_UP_ALL = 1
|
||||
};
|
||||
|
||||
Condition();
|
||||
Condition(int type);
|
||||
~Condition();
|
||||
// Wait on the condition variable. Lock the mutex before calling.
|
||||
status_t wait(Mutex& mutex);
|
||||
// same with relative timeout
|
||||
status_t waitRelative(Mutex& mutex, nsecs_t reltime);
|
||||
// Signal the condition variable, allowing exactly one thread to continue.
|
||||
void signal();
|
||||
// Signal the condition variable, allowing one or all threads to continue.
|
||||
void signal(WakeUpType type) {
|
||||
if (type == WAKE_UP_ONE) {
|
||||
signal();
|
||||
} else {
|
||||
broadcast();
|
||||
}
|
||||
}
|
||||
// Signal the condition variable, allowing all threads to continue.
|
||||
void broadcast();
|
||||
|
||||
private:
|
||||
#if !defined(_WIN32)
|
||||
pthread_cond_t mCond;
|
||||
#else
|
||||
void* mState;
|
||||
#endif
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
inline Condition::Condition() {
|
||||
pthread_cond_init(&mCond, NULL);
|
||||
}
|
||||
inline Condition::Condition(int type) {
|
||||
if (type == SHARED) {
|
||||
pthread_condattr_t attr;
|
||||
pthread_condattr_init(&attr);
|
||||
pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_cond_init(&mCond, &attr);
|
||||
pthread_condattr_destroy(&attr);
|
||||
} else {
|
||||
pthread_cond_init(&mCond, NULL);
|
||||
}
|
||||
}
|
||||
inline Condition::~Condition() {
|
||||
pthread_cond_destroy(&mCond);
|
||||
}
|
||||
inline status_t Condition::wait(Mutex& mutex) {
|
||||
return -pthread_cond_wait(&mCond, &mutex.mMutex);
|
||||
}
|
||||
inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
|
||||
#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = reltime/1000000000;
|
||||
ts.tv_nsec = reltime%1000000000;
|
||||
return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
|
||||
#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
|
||||
struct timespec ts;
|
||||
#if defined(__linux__)
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#else // __APPLE__
|
||||
// we don't support the clocks here.
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
ts.tv_sec = t.tv_sec;
|
||||
ts.tv_nsec= t.tv_usec*1000;
|
||||
#endif
|
||||
ts.tv_sec += reltime/1000000000;
|
||||
ts.tv_nsec+= reltime%1000000000;
|
||||
if (ts.tv_nsec >= 1000000000) {
|
||||
ts.tv_nsec -= 1000000000;
|
||||
ts.tv_sec += 1;
|
||||
}
|
||||
return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
|
||||
#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
|
||||
}
|
||||
inline void Condition::signal() {
|
||||
/*
|
||||
* POSIX says pthread_cond_signal wakes up "one or more" waiting threads.
|
||||
* However bionic follows the glibc guarantee which wakes up "exactly one"
|
||||
* waiting thread.
|
||||
*
|
||||
* man 3 pthread_cond_signal
|
||||
* pthread_cond_signal restarts one of the threads that are waiting on
|
||||
* the condition variable cond. If no threads are waiting on cond,
|
||||
* nothing happens. If several threads are waiting on cond, exactly one
|
||||
* is restarted, but it is not specified which.
|
||||
*/
|
||||
pthread_cond_signal(&mCond);
|
||||
}
|
||||
inline void Condition::broadcast() {
|
||||
pthread_cond_broadcast(&mCond);
|
||||
}
|
||||
|
||||
#endif // !defined(_WIN32)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // _LIBS_UTILS_CONDITON_H
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_UTILS_DEBUG_H
|
||||
#define ANDROID_UTILS_DEBUG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
template<bool> struct CompileTimeAssert;
|
||||
template<> struct CompileTimeAssert<true> {};
|
||||
#define COMPILE_TIME_ASSERT(_exp) \
|
||||
template class CompileTimeAssert< (_exp) >;
|
||||
#endif
|
||||
#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
|
||||
CompileTimeAssert<( _exp )>();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
template<bool C, typename LSH, typename RHS> struct CompileTimeIfElse;
|
||||
template<typename LHS, typename RHS>
|
||||
struct CompileTimeIfElse<true, LHS, RHS> { typedef LHS TYPE; };
|
||||
template<typename LHS, typename RHS>
|
||||
struct CompileTimeIfElse<false, LHS, RHS> { typedef RHS TYPE; };
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_UTILS_DEBUG_H
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Android endian-ness defines.
|
||||
//
|
||||
#ifndef _LIBS_UTILS_ENDIAN_H
|
||||
#define _LIBS_UTILS_ENDIAN_H
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
|
||||
#define __BIG_ENDIAN 0x1000
|
||||
#define __LITTLE_ENDIAN 0x0001
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
|
||||
#else
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
#endif
|
||||
|
||||
#endif /*_LIBS_UTILS_ENDIAN_H*/
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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_ERRORS_H
|
||||
#define ANDROID_ERRORS_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// use this type to return error codes
|
||||
#ifdef HAVE_MS_C_RUNTIME
|
||||
typedef int status_t;
|
||||
#else
|
||||
typedef int32_t status_t;
|
||||
#endif
|
||||
|
||||
/* the MS C runtime lacks a few error codes */
|
||||
|
||||
/*
|
||||
* Error codes.
|
||||
* All error codes are negative values.
|
||||
*/
|
||||
|
||||
// Win32 #defines NO_ERROR as well. It has the same value, so there's no
|
||||
// real conflict, though it's a bit awkward.
|
||||
#ifdef _WIN32
|
||||
# undef NO_ERROR
|
||||
#endif
|
||||
|
||||
enum {
|
||||
OK = 0, // Everything's swell.
|
||||
NO_ERROR = 0, // No errors.
|
||||
|
||||
UNKNOWN_ERROR = (-2147483647-1), // INT32_MIN value
|
||||
|
||||
NO_MEMORY = -ENOMEM,
|
||||
INVALID_OPERATION = -ENOSYS,
|
||||
BAD_VALUE = -EINVAL,
|
||||
BAD_TYPE = (UNKNOWN_ERROR + 1),
|
||||
NAME_NOT_FOUND = -ENOENT,
|
||||
PERMISSION_DENIED = -EPERM,
|
||||
NO_INIT = -ENODEV,
|
||||
ALREADY_EXISTS = -EEXIST,
|
||||
DEAD_OBJECT = -EPIPE,
|
||||
FAILED_TRANSACTION = (UNKNOWN_ERROR + 2),
|
||||
JPARKS_BROKE_IT = -EPIPE,
|
||||
#if !defined(HAVE_MS_C_RUNTIME)
|
||||
BAD_INDEX = -EOVERFLOW,
|
||||
NOT_ENOUGH_DATA = -ENODATA,
|
||||
WOULD_BLOCK = -EWOULDBLOCK,
|
||||
TIMED_OUT = -ETIMEDOUT,
|
||||
UNKNOWN_TRANSACTION = -EBADMSG,
|
||||
#else
|
||||
BAD_INDEX = -E2BIG,
|
||||
NOT_ENOUGH_DATA = (UNKNOWN_ERROR + 3),
|
||||
WOULD_BLOCK = (UNKNOWN_ERROR + 4),
|
||||
TIMED_OUT = (UNKNOWN_ERROR + 5),
|
||||
UNKNOWN_TRANSACTION = (UNKNOWN_ERROR + 6),
|
||||
#endif
|
||||
FDS_NOT_ALLOWED = (UNKNOWN_ERROR + 7),
|
||||
};
|
||||
|
||||
// Restore define; enumeration is in "android" namespace, so the value defined
|
||||
// there won't work for Win32 code in a different namespace.
|
||||
#ifdef _WIN32
|
||||
# define NO_ERROR 0L
|
||||
#endif
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_ERRORS_H
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Encapsulate a shared file mapping.
|
||||
//
|
||||
#ifndef __LIBS_FILE_MAP_H
|
||||
#define __LIBS_FILE_MAP_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Compat.h>
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
// Ensure that we always pull in winsock2.h before windows.h
|
||||
#ifdef HAVE_WINSOCK
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* This represents a memory-mapped file. It might be the entire file or
|
||||
* only part of it. This requires a little bookkeeping because the mapping
|
||||
* needs to be aligned on page boundaries, and in some cases we'd like to
|
||||
* have multiple references to the mapped area without creating additional
|
||||
* maps.
|
||||
*
|
||||
* This always uses MAP_SHARED.
|
||||
*
|
||||
* TODO: we should be able to create a new FileMap that is a subset of
|
||||
* an existing FileMap and shares the underlying mapped pages. Requires
|
||||
* completing the refcounting stuff and possibly introducing the notion
|
||||
* of a FileMap hierarchy.
|
||||
*/
|
||||
class FileMap {
|
||||
public:
|
||||
FileMap(void);
|
||||
|
||||
/*
|
||||
* Create a new mapping on an open file.
|
||||
*
|
||||
* Closing the file descriptor does not unmap the pages, so we don't
|
||||
* claim ownership of the fd.
|
||||
*
|
||||
* Returns "false" on failure.
|
||||
*/
|
||||
bool create(const char* origFileName, int fd,
|
||||
off64_t offset, size_t length, bool readOnly);
|
||||
|
||||
~FileMap(void);
|
||||
|
||||
/*
|
||||
* Return the name of the file this map came from, if known.
|
||||
*/
|
||||
const char* getFileName(void) const { return mFileName; }
|
||||
|
||||
/*
|
||||
* Get a pointer to the piece of the file we requested.
|
||||
*/
|
||||
void* getDataPtr(void) const { return mDataPtr; }
|
||||
|
||||
/*
|
||||
* Get the length we requested.
|
||||
*/
|
||||
size_t getDataLength(void) const { return mDataLength; }
|
||||
|
||||
/*
|
||||
* Get the data offset used to create this map.
|
||||
*/
|
||||
off64_t getDataOffset(void) const { return mDataOffset; }
|
||||
|
||||
/*
|
||||
* This maps directly to madvise() values, but allows us to avoid
|
||||
* including <sys/mman.h> everywhere.
|
||||
*/
|
||||
enum MapAdvice {
|
||||
NORMAL, RANDOM, SEQUENTIAL, WILLNEED, DONTNEED
|
||||
};
|
||||
|
||||
/*
|
||||
* Apply an madvise() call to the entire file.
|
||||
*
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
int advise(MapAdvice advice);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// these are not implemented
|
||||
FileMap(const FileMap& src);
|
||||
const FileMap& operator=(const FileMap& src);
|
||||
|
||||
char* mFileName; // original file name, if known
|
||||
void* mBasePtr; // base of mmap area; page aligned
|
||||
size_t mBaseLength; // length, measured from "mBasePtr"
|
||||
off64_t mDataOffset; // offset used when map was created
|
||||
void* mDataPtr; // start of requested data, offset from base
|
||||
size_t mDataLength; // length, measured from "mDataPtr"
|
||||
#if defined(__MINGW32__)
|
||||
HANDLE mFileHandle; // Win32 file handle
|
||||
HANDLE mFileMapping; // Win32 file mapping handle
|
||||
#endif
|
||||
|
||||
static long mPageSize;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // __LIBS_FILE_MAP_H
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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_UTILS_FLATTENABLE_H
|
||||
#define ANDROID_UTILS_FLATTENABLE_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Debug.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
|
||||
class FlattenableUtils {
|
||||
public:
|
||||
template<int N>
|
||||
static size_t align(size_t size) {
|
||||
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( !(N & (N-1)) );
|
||||
return (size + (N-1)) & ~(N-1);
|
||||
}
|
||||
|
||||
template<int N>
|
||||
static size_t align(void const*& buffer) {
|
||||
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( !(N & (N-1)) );
|
||||
intptr_t b = intptr_t(buffer);
|
||||
buffer = (void*)((intptr_t(buffer) + (N-1)) & ~(N-1));
|
||||
return size_t(intptr_t(buffer) - b);
|
||||
}
|
||||
|
||||
template<int N>
|
||||
static size_t align(void*& buffer) {
|
||||
return align<N>( const_cast<void const*&>(buffer) );
|
||||
}
|
||||
|
||||
static void advance(void*& buffer, size_t& size, size_t offset) {
|
||||
buffer = reinterpret_cast<void*>( intptr_t(buffer) + offset );
|
||||
size -= offset;
|
||||
}
|
||||
|
||||
static void advance(void const*& buffer, size_t& size, size_t offset) {
|
||||
buffer = reinterpret_cast<void const*>( intptr_t(buffer) + offset );
|
||||
size -= offset;
|
||||
}
|
||||
|
||||
// write a POD structure
|
||||
template<typename T>
|
||||
static void write(void*& buffer, size_t& size, const T& value) {
|
||||
*static_cast<T*>(buffer) = value;
|
||||
advance(buffer, size, sizeof(T));
|
||||
}
|
||||
|
||||
// read a POD structure
|
||||
template<typename T>
|
||||
static void read(void const*& buffer, size_t& size, T& value) {
|
||||
value = *static_cast<T const*>(buffer);
|
||||
advance(buffer, size, sizeof(T));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The Flattenable protocol allows an object to serialize itself out
|
||||
* to a byte-buffer and an array of file descriptors.
|
||||
* Flattenable objects must implement this protocol.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
class Flattenable {
|
||||
public:
|
||||
// size in bytes of the flattened object
|
||||
inline size_t getFlattenedSize() const;
|
||||
|
||||
// number of file descriptors to flatten
|
||||
inline size_t getFdCount() const;
|
||||
|
||||
// flattens the object into buffer.
|
||||
// size should be at least of getFlattenedSize()
|
||||
// file descriptors are written in the fds[] array but ownership is
|
||||
// not transfered (ie: they must be dupped by the caller of
|
||||
// flatten() if needed).
|
||||
inline status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
|
||||
|
||||
// unflattens the object from buffer.
|
||||
// size should be equal to the value of getFlattenedSize() when the
|
||||
// object was flattened.
|
||||
// unflattened file descriptors are found in the fds[] array and
|
||||
// don't need to be dupped(). ie: the caller of unflatten doesn't
|
||||
// keep ownership. If a fd is not retained by unflatten() it must be
|
||||
// explicitly closed.
|
||||
inline status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline size_t Flattenable<T>::getFlattenedSize() const {
|
||||
return static_cast<T const*>(this)->T::getFlattenedSize();
|
||||
}
|
||||
template<typename T>
|
||||
inline size_t Flattenable<T>::getFdCount() const {
|
||||
return static_cast<T const*>(this)->T::getFdCount();
|
||||
}
|
||||
template<typename T>
|
||||
inline status_t Flattenable<T>::flatten(
|
||||
void*& buffer, size_t& size, int*& fds, size_t& count) const {
|
||||
return static_cast<T const*>(this)->T::flatten(buffer, size, fds, count);
|
||||
}
|
||||
template<typename T>
|
||||
inline status_t Flattenable<T>::unflatten(
|
||||
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
|
||||
return static_cast<T*>(this)->T::unflatten(buffer, size, fds, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* LightFlattenable is a protocol allowing object to serialize themselves out
|
||||
* to a byte-buffer. Because it doesn't handle file-descriptors,
|
||||
* LightFlattenable is usually more size efficient than Flattenable.
|
||||
* LightFlattenable objects must implement this protocol.
|
||||
*/
|
||||
template <typename T>
|
||||
class LightFlattenable {
|
||||
public:
|
||||
// returns whether this object always flatten into the same size.
|
||||
// for efficiency, this should always be inline.
|
||||
inline bool isFixedSize() const;
|
||||
|
||||
// returns size in bytes of the flattened object. must be a constant.
|
||||
inline size_t getFlattenedSize() const;
|
||||
|
||||
// flattens the object into buffer.
|
||||
inline status_t flatten(void* buffer, size_t size) const;
|
||||
|
||||
// unflattens the object from buffer of given size.
|
||||
inline status_t unflatten(void const* buffer, size_t size);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline bool LightFlattenable<T>::isFixedSize() const {
|
||||
return static_cast<T const*>(this)->T::isFixedSize();
|
||||
}
|
||||
template <typename T>
|
||||
inline size_t LightFlattenable<T>::getFlattenedSize() const {
|
||||
return static_cast<T const*>(this)->T::getFlattenedSize();
|
||||
}
|
||||
template <typename T>
|
||||
inline status_t LightFlattenable<T>::flatten(void* buffer, size_t size) const {
|
||||
return static_cast<T const*>(this)->T::flatten(buffer, size);
|
||||
}
|
||||
template <typename T>
|
||||
inline status_t LightFlattenable<T>::unflatten(void const* buffer, size_t size) {
|
||||
return static_cast<T*>(this)->T::unflatten(buffer, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* LightFlattenablePod is an implementation of the LightFlattenable protocol
|
||||
* for POD (plain-old-data) objects.
|
||||
* Simply derive from LightFlattenablePod<Foo> to make Foo flattenable; no
|
||||
* need to implement any methods; obviously Foo must be a POD structure.
|
||||
*/
|
||||
template <typename T>
|
||||
class LightFlattenablePod : public LightFlattenable<T> {
|
||||
public:
|
||||
inline bool isFixedSize() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline size_t getFlattenedSize() const {
|
||||
return sizeof(T);
|
||||
}
|
||||
inline status_t flatten(void* buffer, size_t size) const {
|
||||
if (size < sizeof(T)) return NO_MEMORY;
|
||||
*reinterpret_cast<T*>(buffer) = *static_cast<T const*>(this);
|
||||
return NO_ERROR;
|
||||
}
|
||||
inline status_t unflatten(void const* buffer, size_t) {
|
||||
*static_cast<T*>(this) = *reinterpret_cast<T const*>(buffer);
|
||||
return NO_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
||||
#endif /* ANDROID_UTILS_FLATTENABLE_H */
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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_FUNCTOR_H
|
||||
#define ANDROID_FUNCTOR_H
|
||||
|
||||
#include <utils/Errors.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class Functor {
|
||||
public:
|
||||
Functor() {}
|
||||
virtual ~Functor() {}
|
||||
virtual status_t operator ()(int /*what*/, void* /*data*/) { return NO_ERROR; }
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_FUNCTOR_H
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.
|
||||
*/
|
||||
|
||||
/* Implementation of Jenkins one-at-a-time hash function. These choices are
|
||||
* optimized for code size and portability, rather than raw speed. But speed
|
||||
* should still be quite good.
|
||||
**/
|
||||
|
||||
#ifndef ANDROID_JENKINS_HASH_H
|
||||
#define ANDROID_JENKINS_HASH_H
|
||||
|
||||
#include <utils/TypeHelpers.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/* The Jenkins hash of a sequence of 32 bit words A, B, C is:
|
||||
* Whiten(Mix(Mix(Mix(0, A), B), C)) */
|
||||
|
||||
inline uint32_t JenkinsHashMix(uint32_t hash, uint32_t data) {
|
||||
hash += data;
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
return hash;
|
||||
}
|
||||
|
||||
hash_t JenkinsHashWhiten(uint32_t hash);
|
||||
|
||||
/* Helpful utility functions for hashing data in 32 bit chunks */
|
||||
uint32_t JenkinsHashMixBytes(uint32_t hash, const uint8_t* bytes, size_t size);
|
||||
|
||||
uint32_t JenkinsHashMixShorts(uint32_t hash, const uint16_t* shorts, size_t size);
|
||||
|
||||
}
|
||||
|
||||
#endif // ANDROID_JENKINS_HASH_H
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_KEYED_VECTOR_H
|
||||
#define ANDROID_KEYED_VECTOR_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <utils/SortedVector.h>
|
||||
#include <utils/TypeHelpers.h>
|
||||
#include <utils/Errors.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
template <typename KEY, typename VALUE>
|
||||
class KeyedVector
|
||||
{
|
||||
public:
|
||||
typedef KEY key_type;
|
||||
typedef VALUE value_type;
|
||||
|
||||
inline KeyedVector();
|
||||
|
||||
/*
|
||||
* empty the vector
|
||||
*/
|
||||
|
||||
inline void clear() { mVector.clear(); }
|
||||
|
||||
/*!
|
||||
* vector stats
|
||||
*/
|
||||
|
||||
//! returns number of items in the vector
|
||||
inline size_t size() const { return mVector.size(); }
|
||||
//! returns whether or not the vector is empty
|
||||
inline bool isEmpty() const { return mVector.isEmpty(); }
|
||||
//! returns how many items can be stored without reallocating the backing store
|
||||
inline size_t capacity() const { return mVector.capacity(); }
|
||||
//! sets the capacity. capacity can never be reduced less than size()
|
||||
inline ssize_t setCapacity(size_t size) { return mVector.setCapacity(size); }
|
||||
|
||||
// returns true if the arguments is known to be identical to this vector
|
||||
inline bool isIdenticalTo(const KeyedVector& rhs) const;
|
||||
|
||||
/*!
|
||||
* accessors
|
||||
*/
|
||||
const VALUE& valueFor(const KEY& key) const;
|
||||
const VALUE& valueAt(size_t index) const;
|
||||
const KEY& keyAt(size_t index) const;
|
||||
ssize_t indexOfKey(const KEY& key) const;
|
||||
const VALUE& operator[] (size_t index) const;
|
||||
|
||||
/*!
|
||||
* modifying the array
|
||||
*/
|
||||
|
||||
VALUE& editValueFor(const KEY& key);
|
||||
VALUE& editValueAt(size_t index);
|
||||
|
||||
/*!
|
||||
* add/insert/replace items
|
||||
*/
|
||||
|
||||
ssize_t add(const KEY& key, const VALUE& item);
|
||||
ssize_t replaceValueFor(const KEY& key, const VALUE& item);
|
||||
ssize_t replaceValueAt(size_t index, const VALUE& item);
|
||||
|
||||
/*!
|
||||
* remove items
|
||||
*/
|
||||
|
||||
ssize_t removeItem(const KEY& key);
|
||||
ssize_t removeItemsAt(size_t index, size_t count = 1);
|
||||
|
||||
private:
|
||||
SortedVector< key_value_pair_t<KEY, VALUE> > mVector;
|
||||
};
|
||||
|
||||
// KeyedVector<KEY, VALUE> can be trivially moved using memcpy() because its
|
||||
// underlying SortedVector can be trivially moved.
|
||||
template<typename KEY, typename VALUE> struct trait_trivial_move<KeyedVector<KEY, VALUE> > {
|
||||
enum { value = trait_trivial_move<SortedVector< key_value_pair_t<KEY, VALUE> > >::value };
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Variation of KeyedVector that holds a default value to return when
|
||||
* valueFor() is called with a key that doesn't exist.
|
||||
*/
|
||||
template <typename KEY, typename VALUE>
|
||||
class DefaultKeyedVector : public KeyedVector<KEY, VALUE>
|
||||
{
|
||||
public:
|
||||
inline DefaultKeyedVector(const VALUE& defValue = VALUE());
|
||||
const VALUE& valueFor(const KEY& key) const;
|
||||
|
||||
private:
|
||||
VALUE mDefault;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
KeyedVector<KEY,VALUE>::KeyedVector()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
bool KeyedVector<KEY,VALUE>::isIdenticalTo(const KeyedVector<KEY,VALUE>& rhs) const {
|
||||
return mVector.array() == rhs.mVector.array();
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
ssize_t KeyedVector<KEY,VALUE>::indexOfKey(const KEY& key) const {
|
||||
return mVector.indexOf( key_value_pair_t<KEY,VALUE>(key) );
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
const VALUE& KeyedVector<KEY,VALUE>::valueFor(const KEY& key) const {
|
||||
ssize_t i = this->indexOfKey(key);
|
||||
LOG_ALWAYS_FATAL_IF(i<0, "%s: key not found", __PRETTY_FUNCTION__);
|
||||
return mVector.itemAt(i).value;
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
const VALUE& KeyedVector<KEY,VALUE>::valueAt(size_t index) const {
|
||||
return mVector.itemAt(index).value;
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
const VALUE& KeyedVector<KEY,VALUE>::operator[] (size_t index) const {
|
||||
return valueAt(index);
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
const KEY& KeyedVector<KEY,VALUE>::keyAt(size_t index) const {
|
||||
return mVector.itemAt(index).key;
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
VALUE& KeyedVector<KEY,VALUE>::editValueFor(const KEY& key) {
|
||||
ssize_t i = this->indexOfKey(key);
|
||||
LOG_ALWAYS_FATAL_IF(i<0, "%s: key not found", __PRETTY_FUNCTION__);
|
||||
return mVector.editItemAt(i).value;
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
VALUE& KeyedVector<KEY,VALUE>::editValueAt(size_t index) {
|
||||
return mVector.editItemAt(index).value;
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
ssize_t KeyedVector<KEY,VALUE>::add(const KEY& key, const VALUE& value) {
|
||||
return mVector.add( key_value_pair_t<KEY,VALUE>(key, value) );
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
ssize_t KeyedVector<KEY,VALUE>::replaceValueFor(const KEY& key, const VALUE& value) {
|
||||
key_value_pair_t<KEY,VALUE> pair(key, value);
|
||||
mVector.remove(pair);
|
||||
return mVector.add(pair);
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
ssize_t KeyedVector<KEY,VALUE>::replaceValueAt(size_t index, const VALUE& item) {
|
||||
if (index<size()) {
|
||||
mVector.editItemAt(index).value = item;
|
||||
return index;
|
||||
}
|
||||
return BAD_INDEX;
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
ssize_t KeyedVector<KEY,VALUE>::removeItem(const KEY& key) {
|
||||
return mVector.remove(key_value_pair_t<KEY,VALUE>(key));
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
ssize_t KeyedVector<KEY, VALUE>::removeItemsAt(size_t index, size_t count) {
|
||||
return mVector.removeItemsAt(index, count);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
DefaultKeyedVector<KEY,VALUE>::DefaultKeyedVector(const VALUE& defValue)
|
||||
: mDefault(defValue)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename KEY, typename VALUE> inline
|
||||
const VALUE& DefaultKeyedVector<KEY,VALUE>::valueFor(const KEY& key) const {
|
||||
ssize_t i = this->indexOfKey(key);
|
||||
return i >= 0 ? KeyedVector<KEY,VALUE>::valueAt(i) : mDefault;
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_KEYED_VECTOR_H
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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 _LIBS_UTILS_LINEAR_TRANSFORM_H
|
||||
#define _LIBS_UTILS_LINEAR_TRANSFORM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// LinearTransform defines a structure which hold the definition of a
|
||||
// transformation from single dimensional coordinate system A into coordinate
|
||||
// system B (and back again). Values in A and in B are 64 bit, the linear
|
||||
// scale factor is expressed as a rational number using two 32 bit values.
|
||||
//
|
||||
// Specifically, let
|
||||
// f(a) = b
|
||||
// F(b) = f^-1(b) = a
|
||||
// then
|
||||
//
|
||||
// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
|
||||
//
|
||||
// and
|
||||
//
|
||||
// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
|
||||
//
|
||||
struct LinearTransform {
|
||||
int64_t a_zero;
|
||||
int64_t b_zero;
|
||||
int32_t a_to_b_numer;
|
||||
uint32_t a_to_b_denom;
|
||||
|
||||
// Transform from A->B
|
||||
// Returns true on success, or false in the case of a singularity or an
|
||||
// overflow.
|
||||
bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
|
||||
|
||||
// Transform from B->A
|
||||
// Returns true on success, or false in the case of a singularity or an
|
||||
// overflow.
|
||||
bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
|
||||
|
||||
// Helpers which will reduce the fraction N/D using Euclid's method.
|
||||
template <class T> static void reduce(T* N, T* D);
|
||||
static void reduce(int32_t* N, uint32_t* D);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // _LIBS_UTILS_LINEAR_TRANSFORM_H
|
||||
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Templated list class. Normally we'd use STL, but we don't have that.
|
||||
// This class mimics STL's interfaces.
|
||||
//
|
||||
// Objects are copied into the list with the '=' operator or with copy-
|
||||
// construction, so if the compiler's auto-generated versions won't work for
|
||||
// you, define your own.
|
||||
//
|
||||
// The only class you want to use from here is "List".
|
||||
//
|
||||
#ifndef _LIBS_UTILS_LIST_H
|
||||
#define _LIBS_UTILS_LIST_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* Doubly-linked list. Instantiate with "List<MyClass> myList".
|
||||
*
|
||||
* Objects added to the list are copied using the assignment operator,
|
||||
* so this must be defined.
|
||||
*/
|
||||
template<typename T>
|
||||
class List
|
||||
{
|
||||
protected:
|
||||
/*
|
||||
* One element in the list.
|
||||
*/
|
||||
class _Node {
|
||||
public:
|
||||
explicit _Node(const T& val) : mVal(val) {}
|
||||
~_Node() {}
|
||||
inline T& getRef() { return mVal; }
|
||||
inline const T& getRef() const { return mVal; }
|
||||
inline _Node* getPrev() const { return mpPrev; }
|
||||
inline _Node* getNext() const { return mpNext; }
|
||||
inline void setVal(const T& val) { mVal = val; }
|
||||
inline void setPrev(_Node* ptr) { mpPrev = ptr; }
|
||||
inline void setNext(_Node* ptr) { mpNext = ptr; }
|
||||
private:
|
||||
friend class List;
|
||||
friend class _ListIterator;
|
||||
T mVal;
|
||||
_Node* mpPrev;
|
||||
_Node* mpNext;
|
||||
};
|
||||
|
||||
/*
|
||||
* Iterator for walking through the list.
|
||||
*/
|
||||
|
||||
template <typename TYPE>
|
||||
struct CONST_ITERATOR {
|
||||
typedef _Node const * NodePtr;
|
||||
typedef const TYPE Type;
|
||||
};
|
||||
|
||||
template <typename TYPE>
|
||||
struct NON_CONST_ITERATOR {
|
||||
typedef _Node* NodePtr;
|
||||
typedef TYPE Type;
|
||||
};
|
||||
|
||||
template<
|
||||
typename U,
|
||||
template <class> class Constness
|
||||
>
|
||||
class _ListIterator {
|
||||
typedef _ListIterator<U, Constness> _Iter;
|
||||
typedef typename Constness<U>::NodePtr _NodePtr;
|
||||
typedef typename Constness<U>::Type _Type;
|
||||
|
||||
explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
|
||||
|
||||
public:
|
||||
_ListIterator() {}
|
||||
_ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
|
||||
~_ListIterator() {}
|
||||
|
||||
// this will handle conversions from iterator to const_iterator
|
||||
// (and also all convertible iterators)
|
||||
// Here, in this implementation, the iterators can be converted
|
||||
// if the nodes can be converted
|
||||
template<typename V> explicit
|
||||
_ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
|
||||
|
||||
|
||||
/*
|
||||
* Dereference operator. Used to get at the juicy insides.
|
||||
*/
|
||||
_Type& operator*() const { return mpNode->getRef(); }
|
||||
_Type* operator->() const { return &(mpNode->getRef()); }
|
||||
|
||||
/*
|
||||
* Iterator comparison.
|
||||
*/
|
||||
inline bool operator==(const _Iter& right) const {
|
||||
return mpNode == right.mpNode; }
|
||||
|
||||
inline bool operator!=(const _Iter& right) const {
|
||||
return mpNode != right.mpNode; }
|
||||
|
||||
/*
|
||||
* handle comparisons between iterator and const_iterator
|
||||
*/
|
||||
template<typename OTHER>
|
||||
inline bool operator==(const OTHER& right) const {
|
||||
return mpNode == right.mpNode; }
|
||||
|
||||
template<typename OTHER>
|
||||
inline bool operator!=(const OTHER& right) const {
|
||||
return mpNode != right.mpNode; }
|
||||
|
||||
/*
|
||||
* Incr/decr, used to move through the list.
|
||||
*/
|
||||
inline _Iter& operator++() { // pre-increment
|
||||
mpNode = mpNode->getNext();
|
||||
return *this;
|
||||
}
|
||||
const _Iter operator++(int) { // post-increment
|
||||
_Iter tmp(*this);
|
||||
mpNode = mpNode->getNext();
|
||||
return tmp;
|
||||
}
|
||||
inline _Iter& operator--() { // pre-increment
|
||||
mpNode = mpNode->getPrev();
|
||||
return *this;
|
||||
}
|
||||
const _Iter operator--(int) { // post-increment
|
||||
_Iter tmp(*this);
|
||||
mpNode = mpNode->getPrev();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline _NodePtr getNode() const { return mpNode; }
|
||||
|
||||
_NodePtr mpNode; /* should be private, but older gcc fails */
|
||||
private:
|
||||
friend class List;
|
||||
};
|
||||
|
||||
public:
|
||||
List() {
|
||||
prep();
|
||||
}
|
||||
List(const List<T>& src) { // copy-constructor
|
||||
prep();
|
||||
insert(begin(), src.begin(), src.end());
|
||||
}
|
||||
virtual ~List() {
|
||||
clear();
|
||||
delete[] (unsigned char*) mpMiddle;
|
||||
}
|
||||
|
||||
typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
|
||||
typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
|
||||
|
||||
List<T>& operator=(const List<T>& right);
|
||||
|
||||
/* returns true if the list is empty */
|
||||
inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
|
||||
|
||||
/* return #of elements in list */
|
||||
size_t size() const {
|
||||
return size_t(distance(begin(), end()));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the first element or one past the last element. The
|
||||
* _Node* we're returning is converted to an "iterator" by a
|
||||
* constructor in _ListIterator.
|
||||
*/
|
||||
inline iterator begin() {
|
||||
return iterator(mpMiddle->getNext());
|
||||
}
|
||||
inline const_iterator begin() const {
|
||||
return const_iterator(const_cast<_Node const*>(mpMiddle->getNext()));
|
||||
}
|
||||
inline iterator end() {
|
||||
return iterator(mpMiddle);
|
||||
}
|
||||
inline const_iterator end() const {
|
||||
return const_iterator(const_cast<_Node const*>(mpMiddle));
|
||||
}
|
||||
|
||||
/* add the object to the head or tail of the list */
|
||||
void push_front(const T& val) { insert(begin(), val); }
|
||||
void push_back(const T& val) { insert(end(), val); }
|
||||
|
||||
/* insert before the current node; returns iterator at new node */
|
||||
iterator insert(iterator posn, const T& val)
|
||||
{
|
||||
_Node* newNode = new _Node(val); // alloc & copy-construct
|
||||
newNode->setNext(posn.getNode());
|
||||
newNode->setPrev(posn.getNode()->getPrev());
|
||||
posn.getNode()->getPrev()->setNext(newNode);
|
||||
posn.getNode()->setPrev(newNode);
|
||||
return iterator(newNode);
|
||||
}
|
||||
|
||||
/* insert a range of elements before the current node */
|
||||
void insert(iterator posn, const_iterator first, const_iterator last) {
|
||||
for ( ; first != last; ++first)
|
||||
insert(posn, *first);
|
||||
}
|
||||
|
||||
/* remove one entry; returns iterator at next node */
|
||||
iterator erase(iterator posn) {
|
||||
_Node* pNext = posn.getNode()->getNext();
|
||||
_Node* pPrev = posn.getNode()->getPrev();
|
||||
pPrev->setNext(pNext);
|
||||
pNext->setPrev(pPrev);
|
||||
delete posn.getNode();
|
||||
return iterator(pNext);
|
||||
}
|
||||
|
||||
/* remove a range of elements */
|
||||
iterator erase(iterator first, iterator last) {
|
||||
while (first != last)
|
||||
erase(first++); // don't erase than incr later!
|
||||
return iterator(last);
|
||||
}
|
||||
|
||||
/* remove all contents of the list */
|
||||
void clear() {
|
||||
_Node* pCurrent = mpMiddle->getNext();
|
||||
_Node* pNext;
|
||||
|
||||
while (pCurrent != mpMiddle) {
|
||||
pNext = pCurrent->getNext();
|
||||
delete pCurrent;
|
||||
pCurrent = pNext;
|
||||
}
|
||||
mpMiddle->setPrev(mpMiddle);
|
||||
mpMiddle->setNext(mpMiddle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Measure the distance between two iterators. On exist, "first"
|
||||
* will be equal to "last". The iterators must refer to the same
|
||||
* list.
|
||||
*
|
||||
* FIXME: This is actually a generic iterator function. It should be a
|
||||
* template function at the top-level with specializations for things like
|
||||
* vector<>, which can just do pointer math). Here we limit it to
|
||||
* _ListIterator of the same type but different constness.
|
||||
*/
|
||||
template<
|
||||
typename U,
|
||||
template <class> class CL,
|
||||
template <class> class CR
|
||||
>
|
||||
ptrdiff_t distance(
|
||||
_ListIterator<U, CL> first, _ListIterator<U, CR> last) const
|
||||
{
|
||||
ptrdiff_t count = 0;
|
||||
while (first != last) {
|
||||
++first;
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* I want a _Node but don't need it to hold valid data. More
|
||||
* to the point, I don't want T's constructor to fire, since it
|
||||
* might have side-effects or require arguments. So, we do this
|
||||
* slightly uncouth storage alloc.
|
||||
*/
|
||||
void prep() {
|
||||
mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
|
||||
mpMiddle->setPrev(mpMiddle);
|
||||
mpMiddle->setNext(mpMiddle);
|
||||
}
|
||||
|
||||
/*
|
||||
* This node plays the role of "pointer to head" and "pointer to tail".
|
||||
* It sits in the middle of a circular list of nodes. The iterator
|
||||
* runs around the circle until it encounters this one.
|
||||
*/
|
||||
_Node* mpMiddle;
|
||||
};
|
||||
|
||||
/*
|
||||
* Assignment operator.
|
||||
*
|
||||
* The simplest way to do this would be to clear out the target list and
|
||||
* fill it with the source. However, we can speed things along by
|
||||
* re-using existing elements.
|
||||
*/
|
||||
template<class T>
|
||||
List<T>& List<T>::operator=(const List<T>& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this; // self-assignment
|
||||
iterator firstDst = begin();
|
||||
iterator lastDst = end();
|
||||
const_iterator firstSrc = right.begin();
|
||||
const_iterator lastSrc = right.end();
|
||||
while (firstSrc != lastSrc && firstDst != lastDst)
|
||||
*firstDst++ = *firstSrc++;
|
||||
if (firstSrc == lastSrc) // ran out of elements in source?
|
||||
erase(firstDst, lastDst); // yes, erase any extras
|
||||
else
|
||||
insert(lastDst, firstSrc, lastSrc); // copy remaining over
|
||||
return *this;
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // _LIBS_UTILS_LIST_H
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// C/C++ logging functions. See the logging documentation for API details.
|
||||
//
|
||||
// We'd like these to be available from C code (in case we import some from
|
||||
// somewhere), so this has a C interface.
|
||||
//
|
||||
// The output will be correct when the log file is shared between multiple
|
||||
// threads and/or multiple processes so long as the operating system
|
||||
// supports O_APPEND. These calls have mutex-protected data structures
|
||||
// and so are NOT reentrant. Do not use LOG in a signal handler.
|
||||
//
|
||||
#ifndef _LIBS_UTILS_LOG_H
|
||||
#define _LIBS_UTILS_LOG_H
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* A very simple utility that yells in the log when an operation takes too long.
|
||||
*/
|
||||
class LogIfSlow {
|
||||
public:
|
||||
LogIfSlow(const char* tag, android_LogPriority priority,
|
||||
int timeoutMillis, const char* message);
|
||||
~LogIfSlow();
|
||||
|
||||
private:
|
||||
const char* const mTag;
|
||||
const android_LogPriority mPriority;
|
||||
const int mTimeoutMillis;
|
||||
const char* const mMessage;
|
||||
const int64_t mStart;
|
||||
};
|
||||
|
||||
/*
|
||||
* Writes the specified debug log message if this block takes longer than the
|
||||
* specified number of milliseconds to run. Includes the time actually taken.
|
||||
*
|
||||
* {
|
||||
* ALOGD_IF_SLOW(50, "Excessive delay doing something.");
|
||||
* doSomething();
|
||||
* }
|
||||
*/
|
||||
#define ALOGD_IF_SLOW(timeoutMillis, message) \
|
||||
android::LogIfSlow _logIfSlow(LOG_TAG, ANDROID_LOG_DEBUG, timeoutMillis, message);
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // _LIBS_UTILS_LOG_H
|
||||
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 UTILS_LOOPER_H
|
||||
#define UTILS_LOOPER_H
|
||||
|
||||
#include <utils/threads.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
#include <sys/epoll.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* NOTE: Since Looper is used to implement the NDK ALooper, the Looper
|
||||
* enums and the signature of Looper_callbackFunc need to align with
|
||||
* that implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* For callback-based event loops, this is the prototype of the function
|
||||
* that is called when a file descriptor event occurs.
|
||||
* It is given the file descriptor it is associated with,
|
||||
* a bitmask of the poll events that were triggered (typically EVENT_INPUT),
|
||||
* and the data pointer that was originally supplied.
|
||||
*
|
||||
* Implementations should return 1 to continue receiving callbacks, or 0
|
||||
* to have this file descriptor and callback unregistered from the looper.
|
||||
*/
|
||||
typedef int (*Looper_callbackFunc)(int fd, int events, void* data);
|
||||
|
||||
/**
|
||||
* A message that can be posted to a Looper.
|
||||
*/
|
||||
struct Message {
|
||||
Message() : what(0) { }
|
||||
Message(int what) : what(what) { }
|
||||
|
||||
/* The message type. (interpretation is left up to the handler) */
|
||||
int what;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a Looper message handler.
|
||||
*
|
||||
* The Looper holds a strong reference to the message handler whenever it has
|
||||
* a message to deliver to it. Make sure to call Looper::removeMessages
|
||||
* to remove any pending messages destined for the handler so that the handler
|
||||
* can be destroyed.
|
||||
*/
|
||||
class MessageHandler : public virtual RefBase {
|
||||
protected:
|
||||
virtual ~MessageHandler() { }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Handles a message.
|
||||
*/
|
||||
virtual void handleMessage(const Message& message) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A simple proxy that holds a weak reference to a message handler.
|
||||
*/
|
||||
class WeakMessageHandler : public MessageHandler {
|
||||
protected:
|
||||
virtual ~WeakMessageHandler();
|
||||
|
||||
public:
|
||||
WeakMessageHandler(const wp<MessageHandler>& handler);
|
||||
virtual void handleMessage(const Message& message);
|
||||
|
||||
private:
|
||||
wp<MessageHandler> mHandler;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A looper callback.
|
||||
*/
|
||||
class LooperCallback : public virtual RefBase {
|
||||
protected:
|
||||
virtual ~LooperCallback() { }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Handles a poll event for the given file descriptor.
|
||||
* It is given the file descriptor it is associated with,
|
||||
* a bitmask of the poll events that were triggered (typically EVENT_INPUT),
|
||||
* and the data pointer that was originally supplied.
|
||||
*
|
||||
* Implementations should return 1 to continue receiving callbacks, or 0
|
||||
* to have this file descriptor and callback unregistered from the looper.
|
||||
*/
|
||||
virtual int handleEvent(int fd, int events, void* data) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wraps a Looper_callbackFunc function pointer.
|
||||
*/
|
||||
class SimpleLooperCallback : public LooperCallback {
|
||||
protected:
|
||||
virtual ~SimpleLooperCallback();
|
||||
|
||||
public:
|
||||
SimpleLooperCallback(Looper_callbackFunc callback);
|
||||
virtual int handleEvent(int fd, int events, void* data);
|
||||
|
||||
private:
|
||||
Looper_callbackFunc mCallback;
|
||||
};
|
||||
|
||||
/**
|
||||
* A polling loop that supports monitoring file descriptor events, optionally
|
||||
* using callbacks. The implementation uses epoll() internally.
|
||||
*
|
||||
* A looper can be associated with a thread although there is no requirement that it must be.
|
||||
*/
|
||||
class Looper : public RefBase {
|
||||
protected:
|
||||
virtual ~Looper();
|
||||
|
||||
public:
|
||||
enum {
|
||||
/**
|
||||
* Result from Looper_pollOnce() and Looper_pollAll():
|
||||
* The poll was awoken using wake() before the timeout expired
|
||||
* and no callbacks were executed and no other file descriptors were ready.
|
||||
*/
|
||||
POLL_WAKE = -1,
|
||||
|
||||
/**
|
||||
* Result from Looper_pollOnce() and Looper_pollAll():
|
||||
* One or more callbacks were executed.
|
||||
*/
|
||||
POLL_CALLBACK = -2,
|
||||
|
||||
/**
|
||||
* Result from Looper_pollOnce() and Looper_pollAll():
|
||||
* The timeout expired.
|
||||
*/
|
||||
POLL_TIMEOUT = -3,
|
||||
|
||||
/**
|
||||
* Result from Looper_pollOnce() and Looper_pollAll():
|
||||
* An error occurred.
|
||||
*/
|
||||
POLL_ERROR = -4,
|
||||
};
|
||||
|
||||
/**
|
||||
* Flags for file descriptor events that a looper can monitor.
|
||||
*
|
||||
* These flag bits can be combined to monitor multiple events at once.
|
||||
*/
|
||||
enum {
|
||||
/**
|
||||
* The file descriptor is available for read operations.
|
||||
*/
|
||||
EVENT_INPUT = 1 << 0,
|
||||
|
||||
/**
|
||||
* The file descriptor is available for write operations.
|
||||
*/
|
||||
EVENT_OUTPUT = 1 << 1,
|
||||
|
||||
/**
|
||||
* The file descriptor has encountered an error condition.
|
||||
*
|
||||
* The looper always sends notifications about errors; it is not necessary
|
||||
* to specify this event flag in the requested event set.
|
||||
*/
|
||||
EVENT_ERROR = 1 << 2,
|
||||
|
||||
/**
|
||||
* The file descriptor was hung up.
|
||||
* For example, indicates that the remote end of a pipe or socket was closed.
|
||||
*
|
||||
* The looper always sends notifications about hangups; it is not necessary
|
||||
* to specify this event flag in the requested event set.
|
||||
*/
|
||||
EVENT_HANGUP = 1 << 3,
|
||||
|
||||
/**
|
||||
* The file descriptor is invalid.
|
||||
* For example, the file descriptor was closed prematurely.
|
||||
*
|
||||
* The looper always sends notifications about invalid file descriptors; it is not necessary
|
||||
* to specify this event flag in the requested event set.
|
||||
*/
|
||||
EVENT_INVALID = 1 << 4,
|
||||
};
|
||||
|
||||
enum {
|
||||
/**
|
||||
* Option for Looper_prepare: this looper will accept calls to
|
||||
* Looper_addFd() that do not have a callback (that is provide NULL
|
||||
* for the callback). In this case the caller of Looper_pollOnce()
|
||||
* or Looper_pollAll() MUST check the return from these functions to
|
||||
* discover when data is available on such fds and process it.
|
||||
*/
|
||||
PREPARE_ALLOW_NON_CALLBACKS = 1<<0
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a looper.
|
||||
*
|
||||
* If allowNonCallbaks is true, the looper will allow file descriptors to be
|
||||
* registered without associated callbacks. This assumes that the caller of
|
||||
* pollOnce() is prepared to handle callback-less events itself.
|
||||
*/
|
||||
Looper(bool allowNonCallbacks);
|
||||
|
||||
/**
|
||||
* Returns whether this looper instance allows the registration of file descriptors
|
||||
* using identifiers instead of callbacks.
|
||||
*/
|
||||
bool getAllowNonCallbacks() const;
|
||||
|
||||
/**
|
||||
* Waits for events to be available, with optional timeout in milliseconds.
|
||||
* Invokes callbacks for all file descriptors on which an event occurred.
|
||||
*
|
||||
* If the timeout is zero, returns immediately without blocking.
|
||||
* If the timeout is negative, waits indefinitely until an event appears.
|
||||
*
|
||||
* Returns POLL_WAKE if the poll was awoken using wake() before
|
||||
* the timeout expired and no callbacks were invoked and no other file
|
||||
* descriptors were ready.
|
||||
*
|
||||
* Returns POLL_CALLBACK if one or more callbacks were invoked.
|
||||
*
|
||||
* Returns POLL_TIMEOUT if there was no data before the given
|
||||
* timeout expired.
|
||||
*
|
||||
* Returns POLL_ERROR if an error occurred.
|
||||
*
|
||||
* Returns a value >= 0 containing an identifier if its file descriptor has data
|
||||
* and it has no callback function (requiring the caller here to handle it).
|
||||
* In this (and only this) case outFd, outEvents and outData will contain the poll
|
||||
* events and data associated with the fd, otherwise they will be set to NULL.
|
||||
*
|
||||
* This method does not return until it has finished invoking the appropriate callbacks
|
||||
* for all file descriptors that were signalled.
|
||||
*/
|
||||
int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
|
||||
inline int pollOnce(int timeoutMillis) {
|
||||
return pollOnce(timeoutMillis, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like pollOnce(), but performs all pending callbacks until all
|
||||
* data has been consumed or a file descriptor is available with no callback.
|
||||
* This function will never return POLL_CALLBACK.
|
||||
*/
|
||||
int pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData);
|
||||
inline int pollAll(int timeoutMillis) {
|
||||
return pollAll(timeoutMillis, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakes the poll asynchronously.
|
||||
*
|
||||
* This method can be called on any thread.
|
||||
* This method returns immediately.
|
||||
*/
|
||||
void wake();
|
||||
|
||||
/**
|
||||
* Adds a new file descriptor to be polled by the looper.
|
||||
* If the same file descriptor was previously added, it is replaced.
|
||||
*
|
||||
* "fd" is the file descriptor to be added.
|
||||
* "ident" is an identifier for this event, which is returned from pollOnce().
|
||||
* The identifier must be >= 0, or POLL_CALLBACK if providing a non-NULL callback.
|
||||
* "events" are the poll events to wake up on. Typically this is EVENT_INPUT.
|
||||
* "callback" is the function to call when there is an event on the file descriptor.
|
||||
* "data" is a private data pointer to supply to the callback.
|
||||
*
|
||||
* There are two main uses of this function:
|
||||
*
|
||||
* (1) If "callback" is non-NULL, then this function will be called when there is
|
||||
* data on the file descriptor. It should execute any events it has pending,
|
||||
* appropriately reading from the file descriptor. The 'ident' is ignored in this case.
|
||||
*
|
||||
* (2) If "callback" is NULL, the 'ident' will be returned by Looper_pollOnce
|
||||
* when its file descriptor has data available, requiring the caller to take
|
||||
* care of processing it.
|
||||
*
|
||||
* Returns 1 if the file descriptor was added, 0 if the arguments were invalid.
|
||||
*
|
||||
* This method can be called on any thread.
|
||||
* This method may block briefly if it needs to wake the poll.
|
||||
*
|
||||
* The callback may either be specified as a bare function pointer or as a smart
|
||||
* pointer callback object. The smart pointer should be preferred because it is
|
||||
* easier to avoid races when the callback is removed from a different thread.
|
||||
* See removeFd() for details.
|
||||
*/
|
||||
int addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data);
|
||||
int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data);
|
||||
|
||||
/**
|
||||
* Removes a previously added file descriptor from the looper.
|
||||
*
|
||||
* When this method returns, it is safe to close the file descriptor since the looper
|
||||
* will no longer have a reference to it. However, it is possible for the callback to
|
||||
* already be running or for it to run one last time if the file descriptor was already
|
||||
* signalled. Calling code is responsible for ensuring that this case is safely handled.
|
||||
* For example, if the callback takes care of removing itself during its own execution either
|
||||
* by returning 0 or by calling this method, then it can be guaranteed to not be invoked
|
||||
* again at any later time unless registered anew.
|
||||
*
|
||||
* A simple way to avoid this problem is to use the version of addFd() that takes
|
||||
* a sp<LooperCallback> instead of a bare function pointer. The LooperCallback will
|
||||
* be released at the appropriate time by the Looper.
|
||||
*
|
||||
* Returns 1 if the file descriptor was removed, 0 if none was previously registered.
|
||||
*
|
||||
* This method can be called on any thread.
|
||||
* This method may block briefly if it needs to wake the poll.
|
||||
*/
|
||||
int removeFd(int fd);
|
||||
|
||||
/**
|
||||
* Enqueues a message to be processed by the specified handler.
|
||||
*
|
||||
* The handler must not be null.
|
||||
* This method can be called on any thread.
|
||||
*/
|
||||
void sendMessage(const sp<MessageHandler>& handler, const Message& message);
|
||||
|
||||
/**
|
||||
* Enqueues a message to be processed by the specified handler after all pending messages
|
||||
* after the specified delay.
|
||||
*
|
||||
* The time delay is specified in uptime nanoseconds.
|
||||
* The handler must not be null.
|
||||
* This method can be called on any thread.
|
||||
*/
|
||||
void sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
|
||||
const Message& message);
|
||||
|
||||
/**
|
||||
* Enqueues a message to be processed by the specified handler after all pending messages
|
||||
* at the specified time.
|
||||
*
|
||||
* The time is specified in uptime nanoseconds.
|
||||
* The handler must not be null.
|
||||
* This method can be called on any thread.
|
||||
*/
|
||||
void sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
|
||||
const Message& message);
|
||||
|
||||
/**
|
||||
* Removes all messages for the specified handler from the queue.
|
||||
*
|
||||
* The handler must not be null.
|
||||
* This method can be called on any thread.
|
||||
*/
|
||||
void removeMessages(const sp<MessageHandler>& handler);
|
||||
|
||||
/**
|
||||
* Removes all messages of a particular type for the specified handler from the queue.
|
||||
*
|
||||
* The handler must not be null.
|
||||
* This method can be called on any thread.
|
||||
*/
|
||||
void removeMessages(const sp<MessageHandler>& handler, int what);
|
||||
|
||||
/**
|
||||
* Returns whether this looper's thread is currently polling for more work to do.
|
||||
* This is a good signal that the loop is still alive rather than being stuck
|
||||
* handling a callback. Note that this method is intrinsically racy, since the
|
||||
* state of the loop can change before you get the result back.
|
||||
*/
|
||||
bool isPolling() const;
|
||||
|
||||
/**
|
||||
* Prepares a looper associated with the calling thread, and returns it.
|
||||
* If the thread already has a looper, it is returned. Otherwise, a new
|
||||
* one is created, associated with the thread, and returned.
|
||||
*
|
||||
* The opts may be PREPARE_ALLOW_NON_CALLBACKS or 0.
|
||||
*/
|
||||
static sp<Looper> prepare(int opts);
|
||||
|
||||
/**
|
||||
* Sets the given looper to be associated with the calling thread.
|
||||
* If another looper is already associated with the thread, it is replaced.
|
||||
*
|
||||
* If "looper" is NULL, removes the currently associated looper.
|
||||
*/
|
||||
static void setForThread(const sp<Looper>& looper);
|
||||
|
||||
/**
|
||||
* Returns the looper associated with the calling thread, or NULL if
|
||||
* there is not one.
|
||||
*/
|
||||
static sp<Looper> getForThread();
|
||||
|
||||
private:
|
||||
struct Request {
|
||||
int fd;
|
||||
int ident;
|
||||
int events;
|
||||
int seq;
|
||||
sp<LooperCallback> callback;
|
||||
void* data;
|
||||
|
||||
void initEventItem(struct epoll_event* eventItem) const;
|
||||
};
|
||||
|
||||
struct Response {
|
||||
int events;
|
||||
Request request;
|
||||
};
|
||||
|
||||
struct MessageEnvelope {
|
||||
MessageEnvelope() : uptime(0) { }
|
||||
|
||||
MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler,
|
||||
const Message& message) : uptime(uptime), handler(handler), message(message) {
|
||||
}
|
||||
|
||||
nsecs_t uptime;
|
||||
sp<MessageHandler> handler;
|
||||
Message message;
|
||||
};
|
||||
|
||||
const bool mAllowNonCallbacks; // immutable
|
||||
|
||||
int mWakeEventFd; // immutable
|
||||
Mutex mLock;
|
||||
|
||||
Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
|
||||
bool mSendingMessage; // guarded by mLock
|
||||
|
||||
// Whether we are currently waiting for work. Not protected by a lock,
|
||||
// any use of it is racy anyway.
|
||||
volatile bool mPolling;
|
||||
|
||||
int mEpollFd; // guarded by mLock but only modified on the looper thread
|
||||
bool mEpollRebuildRequired; // guarded by mLock
|
||||
|
||||
// Locked list of file descriptor monitoring requests.
|
||||
KeyedVector<int, Request> mRequests; // guarded by mLock
|
||||
int mNextRequestSeq;
|
||||
|
||||
// This state is only used privately by pollOnce and does not require a lock since
|
||||
// it runs on a single thread.
|
||||
Vector<Response> mResponses;
|
||||
size_t mResponseIndex;
|
||||
nsecs_t mNextMessageUptime; // set to LLONG_MAX when none
|
||||
|
||||
int pollInner(int timeoutMillis);
|
||||
int removeFd(int fd, int seq);
|
||||
void awoken();
|
||||
void pushResponse(int events, const Request& request);
|
||||
void rebuildEpollLocked();
|
||||
void scheduleEpollRebuildLocked();
|
||||
|
||||
static void initTLSKey();
|
||||
static void threadDestructor(void *st);
|
||||
static void initEpollEvent(struct epoll_event* eventItem);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // UTILS_LOOPER_H
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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_UTILS_LRU_CACHE_H
|
||||
#define ANDROID_UTILS_LRU_CACHE_H
|
||||
|
||||
#include <UniquePtr.h>
|
||||
#include <utils/BasicHashtable.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* GenerationCache callback used when an item is removed
|
||||
*/
|
||||
template<typename EntryKey, typename EntryValue>
|
||||
class OnEntryRemoved {
|
||||
public:
|
||||
virtual ~OnEntryRemoved() { };
|
||||
virtual void operator()(EntryKey& key, EntryValue& value) = 0;
|
||||
}; // class OnEntryRemoved
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
class LruCache {
|
||||
public:
|
||||
explicit LruCache(uint32_t maxCapacity);
|
||||
|
||||
enum Capacity {
|
||||
kUnlimitedCapacity,
|
||||
};
|
||||
|
||||
void setOnEntryRemovedListener(OnEntryRemoved<TKey, TValue>* listener);
|
||||
size_t size() const;
|
||||
const TValue& get(const TKey& key);
|
||||
bool put(const TKey& key, const TValue& value);
|
||||
bool remove(const TKey& key);
|
||||
bool removeOldest();
|
||||
void clear();
|
||||
const TValue& peekOldestValue();
|
||||
|
||||
class Iterator {
|
||||
public:
|
||||
Iterator(const LruCache<TKey, TValue>& cache): mCache(cache), mIndex(-1) {
|
||||
}
|
||||
|
||||
bool next() {
|
||||
mIndex = mCache.mTable->next(mIndex);
|
||||
return (ssize_t)mIndex != -1;
|
||||
}
|
||||
|
||||
size_t index() const {
|
||||
return mIndex;
|
||||
}
|
||||
|
||||
const TValue& value() const {
|
||||
return mCache.mTable->entryAt(mIndex).value;
|
||||
}
|
||||
|
||||
const TKey& key() const {
|
||||
return mCache.mTable->entryAt(mIndex).key;
|
||||
}
|
||||
private:
|
||||
const LruCache<TKey, TValue>& mCache;
|
||||
size_t mIndex;
|
||||
};
|
||||
|
||||
private:
|
||||
LruCache(const LruCache& that); // disallow copy constructor
|
||||
|
||||
struct Entry {
|
||||
TKey key;
|
||||
TValue value;
|
||||
Entry* parent;
|
||||
Entry* child;
|
||||
|
||||
Entry(TKey key_, TValue value_) : key(key_), value(value_), parent(NULL), child(NULL) {
|
||||
}
|
||||
const TKey& getKey() const { return key; }
|
||||
};
|
||||
|
||||
void attachToCache(Entry& entry);
|
||||
void detachFromCache(Entry& entry);
|
||||
void rehash(size_t newCapacity);
|
||||
|
||||
UniquePtr<BasicHashtable<TKey, Entry> > mTable;
|
||||
OnEntryRemoved<TKey, TValue>* mListener;
|
||||
Entry* mOldest;
|
||||
Entry* mYoungest;
|
||||
uint32_t mMaxCapacity;
|
||||
TValue mNullValue;
|
||||
};
|
||||
|
||||
// Implementation is here, because it's fully templated
|
||||
template <typename TKey, typename TValue>
|
||||
LruCache<TKey, TValue>::LruCache(uint32_t maxCapacity)
|
||||
: mTable(new BasicHashtable<TKey, Entry>)
|
||||
, mListener(NULL)
|
||||
, mOldest(NULL)
|
||||
, mYoungest(NULL)
|
||||
, mMaxCapacity(maxCapacity)
|
||||
, mNullValue(NULL) {
|
||||
};
|
||||
|
||||
template<typename K, typename V>
|
||||
void LruCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
size_t LruCache<TKey, TValue>::size() const {
|
||||
return mTable->size();
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
const TValue& LruCache<TKey, TValue>::get(const TKey& key) {
|
||||
hash_t hash = hash_type(key);
|
||||
ssize_t index = mTable->find(-1, hash, key);
|
||||
if (index == -1) {
|
||||
return mNullValue;
|
||||
}
|
||||
Entry& entry = mTable->editEntryAt(index);
|
||||
detachFromCache(entry);
|
||||
attachToCache(entry);
|
||||
return entry.value;
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
bool LruCache<TKey, TValue>::put(const TKey& key, const TValue& value) {
|
||||
if (mMaxCapacity != kUnlimitedCapacity && size() >= mMaxCapacity) {
|
||||
removeOldest();
|
||||
}
|
||||
|
||||
hash_t hash = hash_type(key);
|
||||
ssize_t index = mTable->find(-1, hash, key);
|
||||
if (index >= 0) {
|
||||
return false;
|
||||
}
|
||||
if (!mTable->hasMoreRoom()) {
|
||||
rehash(mTable->capacity() * 2);
|
||||
}
|
||||
|
||||
// Would it be better to initialize a blank entry and assign key, value?
|
||||
Entry initEntry(key, value);
|
||||
index = mTable->add(hash, initEntry);
|
||||
Entry& entry = mTable->editEntryAt(index);
|
||||
attachToCache(entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
bool LruCache<TKey, TValue>::remove(const TKey& key) {
|
||||
hash_t hash = hash_type(key);
|
||||
ssize_t index = mTable->find(-1, hash, key);
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
Entry& entry = mTable->editEntryAt(index);
|
||||
if (mListener) {
|
||||
(*mListener)(entry.key, entry.value);
|
||||
}
|
||||
detachFromCache(entry);
|
||||
mTable->removeAt(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
bool LruCache<TKey, TValue>::removeOldest() {
|
||||
if (mOldest != NULL) {
|
||||
return remove(mOldest->key);
|
||||
// TODO: should probably abort if false
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
const TValue& LruCache<TKey, TValue>::peekOldestValue() {
|
||||
if (mOldest) {
|
||||
return mOldest->value;
|
||||
}
|
||||
return mNullValue;
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
void LruCache<TKey, TValue>::clear() {
|
||||
if (mListener) {
|
||||
for (Entry* p = mOldest; p != NULL; p = p->child) {
|
||||
(*mListener)(p->key, p->value);
|
||||
}
|
||||
}
|
||||
mYoungest = NULL;
|
||||
mOldest = NULL;
|
||||
mTable->clear();
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
void LruCache<TKey, TValue>::attachToCache(Entry& entry) {
|
||||
if (mYoungest == NULL) {
|
||||
mYoungest = mOldest = &entry;
|
||||
} else {
|
||||
entry.parent = mYoungest;
|
||||
mYoungest->child = &entry;
|
||||
mYoungest = &entry;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
void LruCache<TKey, TValue>::detachFromCache(Entry& entry) {
|
||||
if (entry.parent != NULL) {
|
||||
entry.parent->child = entry.child;
|
||||
} else {
|
||||
mOldest = entry.child;
|
||||
}
|
||||
if (entry.child != NULL) {
|
||||
entry.child->parent = entry.parent;
|
||||
} else {
|
||||
mYoungest = entry.parent;
|
||||
}
|
||||
|
||||
entry.parent = NULL;
|
||||
entry.child = NULL;
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
void LruCache<TKey, TValue>::rehash(size_t newCapacity) {
|
||||
UniquePtr<BasicHashtable<TKey, Entry> > oldTable(mTable.release());
|
||||
Entry* oldest = mOldest;
|
||||
|
||||
mOldest = NULL;
|
||||
mYoungest = NULL;
|
||||
mTable.reset(new BasicHashtable<TKey, Entry>(newCapacity));
|
||||
for (Entry* p = oldest; p != NULL; p = p->child) {
|
||||
put(p->key, p->value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // ANDROID_UTILS_LRU_CACHE_H
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 _LIBS_UTILS_MUTEX_H
|
||||
#define _LIBS_UTILS_MUTEX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Condition;
|
||||
|
||||
/*
|
||||
* Simple mutex class. The implementation is system-dependent.
|
||||
*
|
||||
* The mutex must be unlocked by the thread that locked it. They are not
|
||||
* recursive, i.e. the same thread can't lock it multiple times.
|
||||
*/
|
||||
class Mutex {
|
||||
public:
|
||||
enum {
|
||||
PRIVATE = 0,
|
||||
SHARED = 1
|
||||
};
|
||||
|
||||
Mutex();
|
||||
Mutex(const char* name);
|
||||
Mutex(int type, const char* name = NULL);
|
||||
~Mutex();
|
||||
|
||||
// lock or unlock the mutex
|
||||
status_t lock();
|
||||
void unlock();
|
||||
|
||||
// lock if possible; returns 0 on success, error otherwise
|
||||
status_t tryLock();
|
||||
|
||||
#if HAVE_ANDROID_OS
|
||||
// lock the mutex, but don't wait longer than timeoutMilliseconds.
|
||||
// Returns 0 on success, TIMED_OUT for failure due to timeout expiration.
|
||||
//
|
||||
// OSX doesn't have pthread_mutex_timedlock() or equivalent. To keep
|
||||
// capabilities consistent across host OSes, this method is only available
|
||||
// when building Android binaries.
|
||||
status_t timedLock(nsecs_t timeoutMilliseconds);
|
||||
#endif
|
||||
|
||||
// Manages the mutex automatically. It'll be locked when Autolock is
|
||||
// constructed and released when Autolock goes out of scope.
|
||||
class Autolock {
|
||||
public:
|
||||
inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
|
||||
inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
|
||||
inline ~Autolock() { mLock.unlock(); }
|
||||
private:
|
||||
Mutex& mLock;
|
||||
};
|
||||
|
||||
private:
|
||||
friend class Condition;
|
||||
|
||||
// A mutex cannot be copied
|
||||
Mutex(const Mutex&);
|
||||
Mutex& operator = (const Mutex&);
|
||||
|
||||
#if !defined(_WIN32)
|
||||
pthread_mutex_t mMutex;
|
||||
#else
|
||||
void _init();
|
||||
void* mState;
|
||||
#endif
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
inline Mutex::Mutex() {
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
}
|
||||
inline Mutex::Mutex(__attribute__((unused)) const char* name) {
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
}
|
||||
inline Mutex::Mutex(int type, __attribute__((unused)) const char* name) {
|
||||
if (type == SHARED) {
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_mutex_init(&mMutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
} else {
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
}
|
||||
}
|
||||
inline Mutex::~Mutex() {
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
inline status_t Mutex::lock() {
|
||||
return -pthread_mutex_lock(&mMutex);
|
||||
}
|
||||
inline void Mutex::unlock() {
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
inline status_t Mutex::tryLock() {
|
||||
return -pthread_mutex_trylock(&mMutex);
|
||||
}
|
||||
#if HAVE_ANDROID_OS
|
||||
inline status_t Mutex::timedLock(nsecs_t timeoutNs) {
|
||||
const struct timespec ts = {
|
||||
/* .tv_sec = */ static_cast<time_t>(timeoutNs / 1000000000),
|
||||
/* .tv_nsec = */ static_cast<long>(timeoutNs % 1000000000),
|
||||
};
|
||||
return -pthread_mutex_timedlock(&mMutex, &ts);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !defined(_WIN32)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Automatic mutex. Declare one of these at the top of a function.
|
||||
* When the function returns, it will go out of scope, and release the
|
||||
* mutex.
|
||||
*/
|
||||
|
||||
typedef Mutex::Autolock AutoMutex;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // _LIBS_UTILS_MUTEX_H
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2014 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_NATIVE_HANDLE_H
|
||||
#define ANDROID_NATIVE_HANDLE_H
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
|
||||
typedef struct native_handle native_handle_t;
|
||||
|
||||
namespace android {
|
||||
|
||||
class NativeHandle: public LightRefBase<NativeHandle> {
|
||||
public:
|
||||
// Create a refcounted wrapper around a native_handle_t, and declare
|
||||
// whether the wrapper owns the handle (so that it should clean up the
|
||||
// handle upon destruction) or not.
|
||||
// If handle is NULL, no NativeHandle will be created.
|
||||
static sp<NativeHandle> create(native_handle_t* handle, bool ownsHandle);
|
||||
|
||||
const native_handle_t* handle() const {
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
// for access to the destructor
|
||||
friend class LightRefBase<NativeHandle>;
|
||||
|
||||
NativeHandle(native_handle_t* handle, bool ownsHandle);
|
||||
virtual ~NativeHandle();
|
||||
|
||||
native_handle_t* mHandle;
|
||||
bool mOwnsHandle;
|
||||
|
||||
// non-copyable
|
||||
NativeHandle(const NativeHandle&);
|
||||
NativeHandle& operator=(const NativeHandle&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_NATIVE_HANDLE_H
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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_PRINTER_H
|
||||
#define ANDROID_PRINTER_H
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// Interface for printing to an arbitrary data stream
|
||||
class Printer {
|
||||
public:
|
||||
// Print a new line specified by 'string'. \n is appended automatically.
|
||||
// -- Assumes that the string has no new line in it.
|
||||
virtual void printLine(const char* string = "") = 0;
|
||||
|
||||
// Print a new line specified by the format string. \n is appended automatically.
|
||||
// -- Assumes that the resulting string has no new line in it.
|
||||
virtual void printFormatLine(const char* format, ...) __attribute__((format (printf, 2, 3)));
|
||||
|
||||
protected:
|
||||
Printer();
|
||||
virtual ~Printer();
|
||||
}; // class Printer
|
||||
|
||||
// Print to logcat
|
||||
class LogPrinter : public Printer {
|
||||
public:
|
||||
// Create a printer using the specified logcat and log priority
|
||||
// - Unless ignoreBlankLines is false, print blank lines to logcat
|
||||
// (Note that the default ALOG behavior is to ignore blank lines)
|
||||
LogPrinter(const char* logtag,
|
||||
android_LogPriority priority = ANDROID_LOG_DEBUG,
|
||||
const char* prefix = 0,
|
||||
bool ignoreBlankLines = false);
|
||||
|
||||
// Print the specified line to logcat. No \n at the end is necessary.
|
||||
virtual void printLine(const char* string);
|
||||
|
||||
private:
|
||||
void printRaw(const char* string);
|
||||
|
||||
const char* mLogTag;
|
||||
android_LogPriority mPriority;
|
||||
const char* mPrefix;
|
||||
bool mIgnoreBlankLines;
|
||||
}; // class LogPrinter
|
||||
|
||||
// Print to a file descriptor
|
||||
class FdPrinter : public Printer {
|
||||
public:
|
||||
// Create a printer using the specified file descriptor.
|
||||
// - Each line will be prefixed with 'indent' number of blank spaces.
|
||||
// - In addition, each line will be prefixed with the 'prefix' string.
|
||||
FdPrinter(int fd, unsigned int indent = 0, const char* prefix = 0);
|
||||
|
||||
// Print the specified line to the file descriptor. \n is appended automatically.
|
||||
virtual void printLine(const char* string);
|
||||
|
||||
private:
|
||||
enum {
|
||||
MAX_FORMAT_STRING = 20,
|
||||
};
|
||||
|
||||
int mFd;
|
||||
unsigned int mIndent;
|
||||
const char* mPrefix;
|
||||
char mFormatString[MAX_FORMAT_STRING];
|
||||
}; // class FdPrinter
|
||||
|
||||
class String8;
|
||||
|
||||
// Print to a String8
|
||||
class String8Printer : public Printer {
|
||||
public:
|
||||
// Create a printer using the specified String8 as the target.
|
||||
// - In addition, each line will be prefixed with the 'prefix' string.
|
||||
// - target's memory lifetime must be a superset of this String8Printer.
|
||||
String8Printer(String8* target, const char* prefix = 0);
|
||||
|
||||
// Append the specified line to the String8. \n is appended automatically.
|
||||
virtual void printLine(const char* string);
|
||||
|
||||
private:
|
||||
String8* mTarget;
|
||||
const char* mPrefix;
|
||||
}; // class String8Printer
|
||||
|
||||
// Print to an existing Printer by adding a prefix to each line
|
||||
class PrefixPrinter : public Printer {
|
||||
public:
|
||||
// Create a printer using the specified printer as the target.
|
||||
PrefixPrinter(Printer& printer, const char* prefix);
|
||||
|
||||
// Print the line (prefixed with prefix) using the printer.
|
||||
virtual void printLine(const char* string);
|
||||
|
||||
private:
|
||||
Printer& mPrinter;
|
||||
const char* mPrefix;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_PRINTER_H
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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_PROCESS_CALLSTACK_H
|
||||
#define ANDROID_PROCESS_CALLSTACK_H
|
||||
|
||||
#include <utils/CallStack.h>
|
||||
#include <android/log.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class Printer;
|
||||
|
||||
// Collect/print the call stack (function, file, line) traces for all threads in a process.
|
||||
class ProcessCallStack {
|
||||
public:
|
||||
// Create an empty call stack. No-op.
|
||||
ProcessCallStack();
|
||||
// Copy the existing process callstack (no other side effects).
|
||||
ProcessCallStack(const ProcessCallStack& rhs);
|
||||
~ProcessCallStack();
|
||||
|
||||
// Immediately collect the stack traces for all threads.
|
||||
void update();
|
||||
|
||||
// Print all stack traces to the log using the supplied logtag.
|
||||
void log(const char* logtag, android_LogPriority priority = ANDROID_LOG_DEBUG,
|
||||
const char* prefix = 0) const;
|
||||
|
||||
// Dump all stack traces to the specified file descriptor.
|
||||
void dump(int fd, int indent = 0, const char* prefix = 0) const;
|
||||
|
||||
// Return a string (possibly very long) containing all the stack traces.
|
||||
String8 toString(const char* prefix = 0) const;
|
||||
|
||||
// Dump a serialized representation of all the stack traces to the specified printer.
|
||||
void print(Printer& printer) const;
|
||||
|
||||
// Get the number of threads whose stack traces were collected.
|
||||
size_t size() const;
|
||||
|
||||
private:
|
||||
void printInternal(Printer& printer, Printer& csPrinter) const;
|
||||
|
||||
// Reset the process's stack frames and metadata.
|
||||
void clear();
|
||||
|
||||
struct ThreadInfo {
|
||||
CallStack callStack;
|
||||
String8 threadName;
|
||||
};
|
||||
|
||||
// tid -> ThreadInfo
|
||||
KeyedVector<pid_t, ThreadInfo> mThreadMap;
|
||||
// Time that update() was last called
|
||||
struct tm mTimeUpdated;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_PROCESS_CALLSTACK_H
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 _UTILS_PROPERTY_MAP_H
|
||||
#define _UTILS_PROPERTY_MAP_H
|
||||
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Tokenizer.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* Provides a mechanism for passing around string-based property key / value pairs
|
||||
* and loading them from property files.
|
||||
*
|
||||
* The property files have the following simple structure:
|
||||
*
|
||||
* # Comment
|
||||
* key = value
|
||||
*
|
||||
* Keys and values are any sequence of printable ASCII characters.
|
||||
* The '=' separates the key from the value.
|
||||
* The key and value may not contain whitespace.
|
||||
*
|
||||
* The '\' character is reserved for escape sequences and is not currently supported.
|
||||
* The '"" character is reserved for quoting and is not currently supported.
|
||||
* Files that contain the '\' or '"' character will fail to parse.
|
||||
*
|
||||
* The file must not contain duplicate keys.
|
||||
*
|
||||
* TODO Support escape sequences and quoted values when needed.
|
||||
*/
|
||||
class PropertyMap {
|
||||
public:
|
||||
/* Creates an empty property map. */
|
||||
PropertyMap();
|
||||
~PropertyMap();
|
||||
|
||||
/* Clears the property map. */
|
||||
void clear();
|
||||
|
||||
/* Adds a property.
|
||||
* Replaces the property with the same key if it is already present.
|
||||
*/
|
||||
void addProperty(const String8& key, const String8& value);
|
||||
|
||||
/* Returns true if the property map contains the specified key. */
|
||||
bool hasProperty(const String8& key) const;
|
||||
|
||||
/* Gets the value of a property and parses it.
|
||||
* Returns true and sets outValue if the key was found and its value was parsed successfully.
|
||||
* Otherwise returns false and does not modify outValue. (Also logs a warning.)
|
||||
*/
|
||||
bool tryGetProperty(const String8& key, String8& outValue) const;
|
||||
bool tryGetProperty(const String8& key, bool& outValue) const;
|
||||
bool tryGetProperty(const String8& key, int32_t& outValue) const;
|
||||
bool tryGetProperty(const String8& key, float& outValue) const;
|
||||
|
||||
/* Adds all values from the specified property map. */
|
||||
void addAll(const PropertyMap* map);
|
||||
|
||||
/* Gets the underlying property map. */
|
||||
inline const KeyedVector<String8, String8>& getProperties() const { return mProperties; }
|
||||
|
||||
/* Loads a property map from a file. */
|
||||
static status_t load(const String8& filename, PropertyMap** outMap);
|
||||
|
||||
private:
|
||||
class Parser {
|
||||
PropertyMap* mMap;
|
||||
Tokenizer* mTokenizer;
|
||||
|
||||
public:
|
||||
Parser(PropertyMap* map, Tokenizer* tokenizer);
|
||||
~Parser();
|
||||
status_t parse();
|
||||
|
||||
private:
|
||||
status_t parseType();
|
||||
status_t parseKey();
|
||||
status_t parseKeyProperty();
|
||||
status_t parseModifier(const String8& token, int32_t* outMetaState);
|
||||
status_t parseCharacterLiteral(char16_t* outCharacter);
|
||||
};
|
||||
|
||||
KeyedVector<String8, String8> mProperties;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _UTILS_PROPERTY_MAP_H
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 _LIBS_UTILS_RWLOCK_H
|
||||
#define _LIBS_UTILS_RWLOCK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/ThreadDefs.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
/*
|
||||
* Simple mutex class. The implementation is system-dependent.
|
||||
*
|
||||
* The mutex must be unlocked by the thread that locked it. They are not
|
||||
* recursive, i.e. the same thread can't lock it multiple times.
|
||||
*/
|
||||
class RWLock {
|
||||
public:
|
||||
enum {
|
||||
PRIVATE = 0,
|
||||
SHARED = 1
|
||||
};
|
||||
|
||||
RWLock();
|
||||
RWLock(const char* name);
|
||||
RWLock(int type, const char* name = NULL);
|
||||
~RWLock();
|
||||
|
||||
status_t readLock();
|
||||
status_t tryReadLock();
|
||||
status_t writeLock();
|
||||
status_t tryWriteLock();
|
||||
void unlock();
|
||||
|
||||
class AutoRLock {
|
||||
public:
|
||||
inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); }
|
||||
inline ~AutoRLock() { mLock.unlock(); }
|
||||
private:
|
||||
RWLock& mLock;
|
||||
};
|
||||
|
||||
class AutoWLock {
|
||||
public:
|
||||
inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); }
|
||||
inline ~AutoWLock() { mLock.unlock(); }
|
||||
private:
|
||||
RWLock& mLock;
|
||||
};
|
||||
|
||||
private:
|
||||
// A RWLock cannot be copied
|
||||
RWLock(const RWLock&);
|
||||
RWLock& operator = (const RWLock&);
|
||||
|
||||
pthread_rwlock_t mRWLock;
|
||||
};
|
||||
|
||||
inline RWLock::RWLock() {
|
||||
pthread_rwlock_init(&mRWLock, NULL);
|
||||
}
|
||||
inline RWLock::RWLock(__attribute__((unused)) const char* name) {
|
||||
pthread_rwlock_init(&mRWLock, NULL);
|
||||
}
|
||||
inline RWLock::RWLock(int type, __attribute__((unused)) const char* name) {
|
||||
if (type == SHARED) {
|
||||
pthread_rwlockattr_t attr;
|
||||
pthread_rwlockattr_init(&attr);
|
||||
pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_rwlock_init(&mRWLock, &attr);
|
||||
pthread_rwlockattr_destroy(&attr);
|
||||
} else {
|
||||
pthread_rwlock_init(&mRWLock, NULL);
|
||||
}
|
||||
}
|
||||
inline RWLock::~RWLock() {
|
||||
pthread_rwlock_destroy(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::readLock() {
|
||||
return -pthread_rwlock_rdlock(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::tryReadLock() {
|
||||
return -pthread_rwlock_tryrdlock(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::writeLock() {
|
||||
return -pthread_rwlock_wrlock(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::tryWriteLock() {
|
||||
return -pthread_rwlock_trywrlock(&mRWLock);
|
||||
}
|
||||
inline void RWLock::unlock() {
|
||||
pthread_rwlock_unlock(&mRWLock);
|
||||
}
|
||||
|
||||
#endif // !defined(_WIN32)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // _LIBS_UTILS_RWLOCK_H
|
||||
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_REF_BASE_H
|
||||
#define ANDROID_REF_BASE_H
|
||||
|
||||
#include <cutils/atomic.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <utils/StrongPointer.h>
|
||||
#include <utils/TypeHelpers.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
|
||||
class TextOutput;
|
||||
TextOutput& printWeakPointer(TextOutput& to, const void* val);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define COMPARE_WEAK(_op_) \
|
||||
inline bool operator _op_ (const sp<T>& o) const { \
|
||||
return m_ptr _op_ o.m_ptr; \
|
||||
} \
|
||||
inline bool operator _op_ (const T* o) const { \
|
||||
return m_ptr _op_ o; \
|
||||
} \
|
||||
template<typename U> \
|
||||
inline bool operator _op_ (const sp<U>& o) const { \
|
||||
return m_ptr _op_ o.m_ptr; \
|
||||
} \
|
||||
template<typename U> \
|
||||
inline bool operator _op_ (const U* o) const { \
|
||||
return m_ptr _op_ o; \
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class ReferenceRenamer {
|
||||
protected:
|
||||
// destructor is purposedly not virtual so we avoid code overhead from
|
||||
// subclasses; we have to make it protected to guarantee that it
|
||||
// cannot be called from this base class (and to make strict compilers
|
||||
// happy).
|
||||
~ReferenceRenamer() { }
|
||||
public:
|
||||
virtual void operator()(size_t i) const = 0;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class RefBase
|
||||
{
|
||||
public:
|
||||
void incStrong(const void* id) const;
|
||||
void decStrong(const void* id) const;
|
||||
|
||||
void forceIncStrong(const void* id) const;
|
||||
|
||||
//! DEBUGGING ONLY: Get current strong ref count.
|
||||
int32_t getStrongCount() const;
|
||||
|
||||
class weakref_type
|
||||
{
|
||||
public:
|
||||
RefBase* refBase() const;
|
||||
|
||||
void incWeak(const void* id);
|
||||
void decWeak(const void* id);
|
||||
|
||||
// acquires a strong reference if there is already one.
|
||||
bool attemptIncStrong(const void* id);
|
||||
|
||||
// acquires a weak reference if there is already one.
|
||||
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
|
||||
// for proper use.
|
||||
bool attemptIncWeak(const void* id);
|
||||
|
||||
//! DEBUGGING ONLY: Get current weak ref count.
|
||||
int32_t getWeakCount() const;
|
||||
|
||||
//! DEBUGGING ONLY: Print references held on object.
|
||||
void printRefs() const;
|
||||
|
||||
//! DEBUGGING ONLY: Enable tracking for this object.
|
||||
// enable -- enable/disable tracking
|
||||
// retain -- when tracking is enable, if true, then we save a stack trace
|
||||
// for each reference and dereference; when retain == false, we
|
||||
// match up references and dereferences and keep only the
|
||||
// outstanding ones.
|
||||
|
||||
void trackMe(bool enable, bool retain);
|
||||
};
|
||||
|
||||
weakref_type* createWeak(const void* id) const;
|
||||
|
||||
weakref_type* getWeakRefs() const;
|
||||
|
||||
//! DEBUGGING ONLY: Print references held on object.
|
||||
inline void printRefs() const { getWeakRefs()->printRefs(); }
|
||||
|
||||
//! DEBUGGING ONLY: Enable tracking of object.
|
||||
inline void trackMe(bool enable, bool retain)
|
||||
{
|
||||
getWeakRefs()->trackMe(enable, retain);
|
||||
}
|
||||
|
||||
typedef RefBase basetype;
|
||||
|
||||
protected:
|
||||
RefBase();
|
||||
virtual ~RefBase();
|
||||
|
||||
//! Flags for extendObjectLifetime()
|
||||
enum {
|
||||
OBJECT_LIFETIME_STRONG = 0x0000,
|
||||
OBJECT_LIFETIME_WEAK = 0x0001,
|
||||
OBJECT_LIFETIME_MASK = 0x0001
|
||||
};
|
||||
|
||||
void extendObjectLifetime(int32_t mode);
|
||||
|
||||
//! Flags for onIncStrongAttempted()
|
||||
enum {
|
||||
FIRST_INC_STRONG = 0x0001
|
||||
};
|
||||
|
||||
virtual void onFirstRef();
|
||||
virtual void onLastStrongRef(const void* id);
|
||||
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
|
||||
virtual void onLastWeakRef(const void* id);
|
||||
|
||||
private:
|
||||
friend class weakref_type;
|
||||
class weakref_impl;
|
||||
|
||||
RefBase(const RefBase& o);
|
||||
RefBase& operator=(const RefBase& o);
|
||||
|
||||
private:
|
||||
friend class ReferenceMover;
|
||||
|
||||
static void renameRefs(size_t n, const ReferenceRenamer& renamer);
|
||||
|
||||
static void renameRefId(weakref_type* ref,
|
||||
const void* old_id, const void* new_id);
|
||||
|
||||
static void renameRefId(RefBase* ref,
|
||||
const void* old_id, const void* new_id);
|
||||
|
||||
weakref_impl* const mRefs;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <class T>
|
||||
class LightRefBase
|
||||
{
|
||||
public:
|
||||
inline LightRefBase() : mCount(0) { }
|
||||
inline void incStrong(__attribute__((unused)) const void* id) const {
|
||||
android_atomic_inc(&mCount);
|
||||
}
|
||||
inline void decStrong(__attribute__((unused)) const void* id) const {
|
||||
if (android_atomic_dec(&mCount) == 1) {
|
||||
delete static_cast<const T*>(this);
|
||||
}
|
||||
}
|
||||
//! DEBUGGING ONLY: Get current strong ref count.
|
||||
inline int32_t getStrongCount() const {
|
||||
return mCount;
|
||||
}
|
||||
|
||||
typedef LightRefBase<T> basetype;
|
||||
|
||||
protected:
|
||||
inline ~LightRefBase() { }
|
||||
|
||||
private:
|
||||
friend class ReferenceMover;
|
||||
inline static void renameRefs(size_t n, const ReferenceRenamer& renamer) { }
|
||||
inline static void renameRefId(T* ref,
|
||||
const void* old_id, const void* new_id) { }
|
||||
|
||||
private:
|
||||
mutable volatile int32_t mCount;
|
||||
};
|
||||
|
||||
// This is a wrapper around LightRefBase that simply enforces a virtual
|
||||
// destructor to eliminate the template requirement of LightRefBase
|
||||
class VirtualLightRefBase : public LightRefBase<VirtualLightRefBase> {
|
||||
public:
|
||||
virtual ~VirtualLightRefBase() {}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
class wp
|
||||
{
|
||||
public:
|
||||
typedef typename RefBase::weakref_type weakref_type;
|
||||
|
||||
inline wp() : m_ptr(0) { }
|
||||
|
||||
wp(T* other);
|
||||
wp(const wp<T>& other);
|
||||
wp(const sp<T>& other);
|
||||
template<typename U> wp(U* other);
|
||||
template<typename U> wp(const sp<U>& other);
|
||||
template<typename U> wp(const wp<U>& other);
|
||||
|
||||
~wp();
|
||||
|
||||
// Assignment
|
||||
|
||||
wp& operator = (T* other);
|
||||
wp& operator = (const wp<T>& other);
|
||||
wp& operator = (const sp<T>& other);
|
||||
|
||||
template<typename U> wp& operator = (U* other);
|
||||
template<typename U> wp& operator = (const wp<U>& other);
|
||||
template<typename U> wp& operator = (const sp<U>& other);
|
||||
|
||||
void set_object_and_refs(T* other, weakref_type* refs);
|
||||
|
||||
// promotion to sp
|
||||
|
||||
sp<T> promote() const;
|
||||
|
||||
// Reset
|
||||
|
||||
void clear();
|
||||
|
||||
// Accessors
|
||||
|
||||
inline weakref_type* get_refs() const { return m_refs; }
|
||||
|
||||
inline T* unsafe_get() const { return m_ptr; }
|
||||
|
||||
// Operators
|
||||
|
||||
COMPARE_WEAK(==)
|
||||
COMPARE_WEAK(!=)
|
||||
COMPARE_WEAK(>)
|
||||
COMPARE_WEAK(<)
|
||||
COMPARE_WEAK(<=)
|
||||
COMPARE_WEAK(>=)
|
||||
|
||||
inline bool operator == (const wp<T>& o) const {
|
||||
return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
|
||||
}
|
||||
template<typename U>
|
||||
inline bool operator == (const wp<U>& o) const {
|
||||
return m_ptr == o.m_ptr;
|
||||
}
|
||||
|
||||
inline bool operator > (const wp<T>& o) const {
|
||||
return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
|
||||
}
|
||||
template<typename U>
|
||||
inline bool operator > (const wp<U>& o) const {
|
||||
return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
|
||||
}
|
||||
|
||||
inline bool operator < (const wp<T>& o) const {
|
||||
return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
|
||||
}
|
||||
template<typename U>
|
||||
inline bool operator < (const wp<U>& o) const {
|
||||
return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
|
||||
}
|
||||
inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
|
||||
template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
|
||||
inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
|
||||
template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
|
||||
inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
|
||||
template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
|
||||
|
||||
private:
|
||||
template<typename Y> friend class sp;
|
||||
template<typename Y> friend class wp;
|
||||
|
||||
T* m_ptr;
|
||||
weakref_type* m_refs;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
TextOutput& operator<<(TextOutput& to, const wp<T>& val);
|
||||
|
||||
#undef COMPARE_WEAK
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No user serviceable parts below here.
|
||||
|
||||
template<typename T>
|
||||
wp<T>::wp(T* other)
|
||||
: m_ptr(other)
|
||||
{
|
||||
if (other) m_refs = other->createWeak(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
wp<T>::wp(const wp<T>& other)
|
||||
: m_ptr(other.m_ptr), m_refs(other.m_refs)
|
||||
{
|
||||
if (m_ptr) m_refs->incWeak(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
wp<T>::wp(const sp<T>& other)
|
||||
: m_ptr(other.m_ptr)
|
||||
{
|
||||
if (m_ptr) {
|
||||
m_refs = m_ptr->createWeak(this);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> template<typename U>
|
||||
wp<T>::wp(U* other)
|
||||
: m_ptr(other)
|
||||
{
|
||||
if (other) m_refs = other->createWeak(this);
|
||||
}
|
||||
|
||||
template<typename T> template<typename U>
|
||||
wp<T>::wp(const wp<U>& other)
|
||||
: m_ptr(other.m_ptr)
|
||||
{
|
||||
if (m_ptr) {
|
||||
m_refs = other.m_refs;
|
||||
m_refs->incWeak(this);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> template<typename U>
|
||||
wp<T>::wp(const sp<U>& other)
|
||||
: m_ptr(other.m_ptr)
|
||||
{
|
||||
if (m_ptr) {
|
||||
m_refs = m_ptr->createWeak(this);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
wp<T>::~wp()
|
||||
{
|
||||
if (m_ptr) m_refs->decWeak(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
wp<T>& wp<T>::operator = (T* other)
|
||||
{
|
||||
weakref_type* newRefs =
|
||||
other ? other->createWeak(this) : 0;
|
||||
if (m_ptr) m_refs->decWeak(this);
|
||||
m_ptr = other;
|
||||
m_refs = newRefs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
wp<T>& wp<T>::operator = (const wp<T>& other)
|
||||
{
|
||||
weakref_type* otherRefs(other.m_refs);
|
||||
T* otherPtr(other.m_ptr);
|
||||
if (otherPtr) otherRefs->incWeak(this);
|
||||
if (m_ptr) m_refs->decWeak(this);
|
||||
m_ptr = otherPtr;
|
||||
m_refs = otherRefs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
wp<T>& wp<T>::operator = (const sp<T>& other)
|
||||
{
|
||||
weakref_type* newRefs =
|
||||
other != NULL ? other->createWeak(this) : 0;
|
||||
T* otherPtr(other.m_ptr);
|
||||
if (m_ptr) m_refs->decWeak(this);
|
||||
m_ptr = otherPtr;
|
||||
m_refs = newRefs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> template<typename U>
|
||||
wp<T>& wp<T>::operator = (U* other)
|
||||
{
|
||||
weakref_type* newRefs =
|
||||
other ? other->createWeak(this) : 0;
|
||||
if (m_ptr) m_refs->decWeak(this);
|
||||
m_ptr = other;
|
||||
m_refs = newRefs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> template<typename U>
|
||||
wp<T>& wp<T>::operator = (const wp<U>& other)
|
||||
{
|
||||
weakref_type* otherRefs(other.m_refs);
|
||||
U* otherPtr(other.m_ptr);
|
||||
if (otherPtr) otherRefs->incWeak(this);
|
||||
if (m_ptr) m_refs->decWeak(this);
|
||||
m_ptr = otherPtr;
|
||||
m_refs = otherRefs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> template<typename U>
|
||||
wp<T>& wp<T>::operator = (const sp<U>& other)
|
||||
{
|
||||
weakref_type* newRefs =
|
||||
other != NULL ? other->createWeak(this) : 0;
|
||||
U* otherPtr(other.m_ptr);
|
||||
if (m_ptr) m_refs->decWeak(this);
|
||||
m_ptr = otherPtr;
|
||||
m_refs = newRefs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
|
||||
{
|
||||
if (other) refs->incWeak(this);
|
||||
if (m_ptr) m_refs->decWeak(this);
|
||||
m_ptr = other;
|
||||
m_refs = refs;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
sp<T> wp<T>::promote() const
|
||||
{
|
||||
sp<T> result;
|
||||
if (m_ptr && m_refs->attemptIncStrong(&result)) {
|
||||
result.set_pointer(m_ptr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void wp<T>::clear()
|
||||
{
|
||||
if (m_ptr) {
|
||||
m_refs->decWeak(this);
|
||||
m_ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
|
||||
{
|
||||
return printWeakPointer(to, val.unsafe_get());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// this class just serves as a namespace so TYPE::moveReferences can stay
|
||||
// private.
|
||||
class ReferenceMover {
|
||||
public:
|
||||
// it would be nice if we could make sure no extra code is generated
|
||||
// for sp<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
|
||||
// Using a sp<RefBase> override doesn't work; it's a bit like we wanted
|
||||
// a template<typename TYPE inherits RefBase> template...
|
||||
|
||||
template<typename TYPE> static inline
|
||||
void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
|
||||
|
||||
class Renamer : public ReferenceRenamer {
|
||||
sp<TYPE>* d;
|
||||
sp<TYPE> const* s;
|
||||
virtual void operator()(size_t i) const {
|
||||
// The id are known to be the sp<>'s this pointer
|
||||
TYPE::renameRefId(d[i].get(), &s[i], &d[i]);
|
||||
}
|
||||
public:
|
||||
Renamer(sp<TYPE>* d, sp<TYPE> const* s) : d(d), s(s) { }
|
||||
virtual ~Renamer() { }
|
||||
};
|
||||
|
||||
memmove(d, s, n*sizeof(sp<TYPE>));
|
||||
TYPE::renameRefs(n, Renamer(d, s));
|
||||
}
|
||||
|
||||
|
||||
template<typename TYPE> static inline
|
||||
void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
|
||||
|
||||
class Renamer : public ReferenceRenamer {
|
||||
wp<TYPE>* d;
|
||||
wp<TYPE> const* s;
|
||||
virtual void operator()(size_t i) const {
|
||||
// The id are known to be the wp<>'s this pointer
|
||||
TYPE::renameRefId(d[i].get_refs(), &s[i], &d[i]);
|
||||
}
|
||||
public:
|
||||
Renamer(wp<TYPE>* d, wp<TYPE> const* s) : d(d), s(s) { }
|
||||
virtual ~Renamer() { }
|
||||
};
|
||||
|
||||
memmove(d, s, n*sizeof(wp<TYPE>));
|
||||
TYPE::renameRefs(n, Renamer(d, s));
|
||||
}
|
||||
};
|
||||
|
||||
// specialization for moving sp<> and wp<> types.
|
||||
// these are used by the [Sorted|Keyed]Vector<> implementations
|
||||
// sp<> and wp<> need to be handled specially, because they do not
|
||||
// have trivial copy operation in the general case (see RefBase.cpp
|
||||
// when DEBUG ops are enabled), but can be implemented very
|
||||
// efficiently in most cases.
|
||||
|
||||
template<typename TYPE> inline
|
||||
void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
|
||||
ReferenceMover::move_references(d, s, n);
|
||||
}
|
||||
|
||||
template<typename TYPE> inline
|
||||
void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
|
||||
ReferenceMover::move_references(d, s, n);
|
||||
}
|
||||
|
||||
template<typename TYPE> inline
|
||||
void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
|
||||
ReferenceMover::move_references(d, s, n);
|
||||
}
|
||||
|
||||
template<typename TYPE> inline
|
||||
void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
|
||||
ReferenceMover::move_references(d, s, n);
|
||||
}
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_REF_BASE_H
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_SHARED_BUFFER_H
|
||||
#define ANDROID_SHARED_BUFFER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
class SharedBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
/* flags to use with release() */
|
||||
enum {
|
||||
eKeepStorage = 0x00000001
|
||||
};
|
||||
|
||||
/*! allocate a buffer of size 'size' and acquire() it.
|
||||
* call release() to free it.
|
||||
*/
|
||||
static SharedBuffer* alloc(size_t size);
|
||||
|
||||
/*! free the memory associated with the SharedBuffer.
|
||||
* Fails if there are any users associated with this SharedBuffer.
|
||||
* In other words, the buffer must have been release by all its
|
||||
* users.
|
||||
*/
|
||||
static ssize_t dealloc(const SharedBuffer* released);
|
||||
|
||||
//! access the data for read
|
||||
inline const void* data() const;
|
||||
|
||||
//! access the data for read/write
|
||||
inline void* data();
|
||||
|
||||
//! get size of the buffer
|
||||
inline size_t size() const;
|
||||
|
||||
//! get back a SharedBuffer object from its data
|
||||
static inline SharedBuffer* bufferFromData(void* data);
|
||||
|
||||
//! get back a SharedBuffer object from its data
|
||||
static inline const SharedBuffer* bufferFromData(const void* data);
|
||||
|
||||
//! get the size of a SharedBuffer object from its data
|
||||
static inline size_t sizeFromData(const void* data);
|
||||
|
||||
//! edit the buffer (get a writtable, or non-const, version of it)
|
||||
SharedBuffer* edit() const;
|
||||
|
||||
//! edit the buffer, resizing if needed
|
||||
SharedBuffer* editResize(size_t size) const;
|
||||
|
||||
//! like edit() but fails if a copy is required
|
||||
SharedBuffer* attemptEdit() const;
|
||||
|
||||
//! resize and edit the buffer, loose it's content.
|
||||
SharedBuffer* reset(size_t size) const;
|
||||
|
||||
//! acquire/release a reference on this buffer
|
||||
void acquire() const;
|
||||
|
||||
/*! release a reference on this buffer, with the option of not
|
||||
* freeing the memory associated with it if it was the last reference
|
||||
* returns the previous reference count
|
||||
*/
|
||||
int32_t release(uint32_t flags = 0) const;
|
||||
|
||||
//! returns wether or not we're the only owner
|
||||
inline bool onlyOwner() const;
|
||||
|
||||
|
||||
private:
|
||||
inline SharedBuffer() { }
|
||||
inline ~SharedBuffer() { }
|
||||
SharedBuffer(const SharedBuffer&);
|
||||
SharedBuffer& operator = (const SharedBuffer&);
|
||||
|
||||
// 16 bytes. must be sized to preserve correct alignment.
|
||||
mutable int32_t mRefs;
|
||||
size_t mSize;
|
||||
uint32_t mReserved[2];
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const void* SharedBuffer::data() const {
|
||||
return this + 1;
|
||||
}
|
||||
|
||||
void* SharedBuffer::data() {
|
||||
return this + 1;
|
||||
}
|
||||
|
||||
size_t SharedBuffer::size() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
SharedBuffer* SharedBuffer::bufferFromData(void* data) {
|
||||
return data ? static_cast<SharedBuffer *>(data)-1 : 0;
|
||||
}
|
||||
|
||||
const SharedBuffer* SharedBuffer::bufferFromData(const void* data) {
|
||||
return data ? static_cast<const SharedBuffer *>(data)-1 : 0;
|
||||
}
|
||||
|
||||
size_t SharedBuffer::sizeFromData(const void* data) {
|
||||
return data ? bufferFromData(data)->mSize : 0;
|
||||
}
|
||||
|
||||
bool SharedBuffer::onlyOwner() const {
|
||||
return (mRefs == 1);
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_VECTOR_H
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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_UTILS_SINGLETON_H
|
||||
#define ANDROID_UTILS_SINGLETON_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/threads.h>
|
||||
#include <cutils/compiler.h>
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename TYPE>
|
||||
class ANDROID_API Singleton
|
||||
{
|
||||
public:
|
||||
static TYPE& getInstance() {
|
||||
Mutex::Autolock _l(sLock);
|
||||
TYPE* instance = sInstance;
|
||||
if (instance == 0) {
|
||||
instance = new TYPE();
|
||||
sInstance = instance;
|
||||
}
|
||||
return *instance;
|
||||
}
|
||||
|
||||
static bool hasInstance() {
|
||||
Mutex::Autolock _l(sLock);
|
||||
return sInstance != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
~Singleton() { };
|
||||
Singleton() { };
|
||||
|
||||
private:
|
||||
Singleton(const Singleton&);
|
||||
Singleton& operator = (const Singleton&);
|
||||
static Mutex sLock;
|
||||
static TYPE* sInstance;
|
||||
};
|
||||
|
||||
/*
|
||||
* use ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) in your implementation file
|
||||
* (eg: <TYPE>.cpp) to create the static instance of Singleton<>'s attributes,
|
||||
* and avoid to have a copy of them in each compilation units Singleton<TYPE>
|
||||
* is used.
|
||||
* NOTE: we use a version of Mutex ctor that takes a parameter, because
|
||||
* for some unknown reason using the default ctor doesn't emit the variable!
|
||||
*/
|
||||
|
||||
#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) \
|
||||
template<> ::android::Mutex \
|
||||
(::android::Singleton< TYPE >::sLock)(::android::Mutex::PRIVATE); \
|
||||
template<> TYPE* ::android::Singleton< TYPE >::sInstance(0); \
|
||||
template class ::android::Singleton< TYPE >;
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_UTILS_SINGLETON_H
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_SORTED_VECTOR_H
|
||||
#define ANDROID_SORTED_VECTOR_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <utils/Vector.h>
|
||||
#include <utils/VectorImpl.h>
|
||||
#include <utils/TypeHelpers.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
template <class TYPE>
|
||||
class SortedVector : private SortedVectorImpl
|
||||
{
|
||||
friend class Vector<TYPE>;
|
||||
|
||||
public:
|
||||
typedef TYPE value_type;
|
||||
|
||||
/*!
|
||||
* Constructors and destructors
|
||||
*/
|
||||
|
||||
SortedVector();
|
||||
SortedVector(const SortedVector<TYPE>& rhs);
|
||||
virtual ~SortedVector();
|
||||
|
||||
/*! copy operator */
|
||||
const SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
|
||||
SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
|
||||
|
||||
/*
|
||||
* empty the vector
|
||||
*/
|
||||
|
||||
inline void clear() { VectorImpl::clear(); }
|
||||
|
||||
/*!
|
||||
* vector stats
|
||||
*/
|
||||
|
||||
//! returns number of items in the vector
|
||||
inline size_t size() const { return VectorImpl::size(); }
|
||||
//! returns whether or not the vector is empty
|
||||
inline bool isEmpty() const { return VectorImpl::isEmpty(); }
|
||||
//! returns how many items can be stored without reallocating the backing store
|
||||
inline size_t capacity() const { return VectorImpl::capacity(); }
|
||||
//! sets the capacity. capacity can never be reduced less than size()
|
||||
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
|
||||
|
||||
/*!
|
||||
* C-style array access
|
||||
*/
|
||||
|
||||
//! read-only C-style access
|
||||
inline const TYPE* array() const;
|
||||
|
||||
//! read-write C-style access. BE VERY CAREFUL when modifying the array
|
||||
//! you must keep it sorted! You usually don't use this function.
|
||||
TYPE* editArray();
|
||||
|
||||
//! finds the index of an item
|
||||
ssize_t indexOf(const TYPE& item) const;
|
||||
|
||||
//! finds where this item should be inserted
|
||||
size_t orderOf(const TYPE& item) const;
|
||||
|
||||
|
||||
/*!
|
||||
* accessors
|
||||
*/
|
||||
|
||||
//! read-only access to an item at a given index
|
||||
inline const TYPE& operator [] (size_t index) const;
|
||||
//! alternate name for operator []
|
||||
inline const TYPE& itemAt(size_t index) const;
|
||||
//! stack-usage of the vector. returns the top of the stack (last element)
|
||||
const TYPE& top() const;
|
||||
|
||||
/*!
|
||||
* modifying the array
|
||||
*/
|
||||
|
||||
//! add an item in the right place (and replace the one that is there)
|
||||
ssize_t add(const TYPE& item);
|
||||
|
||||
//! editItemAt() MUST NOT change the order of this item
|
||||
TYPE& editItemAt(size_t index) {
|
||||
return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
|
||||
}
|
||||
|
||||
//! merges a vector into this one
|
||||
ssize_t merge(const Vector<TYPE>& vector);
|
||||
ssize_t merge(const SortedVector<TYPE>& vector);
|
||||
|
||||
//! removes an item
|
||||
ssize_t remove(const TYPE&);
|
||||
|
||||
//! remove several items
|
||||
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
|
||||
//! remove one item
|
||||
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
|
||||
|
||||
protected:
|
||||
virtual void do_construct(void* storage, size_t num) const;
|
||||
virtual void do_destroy(void* storage, size_t num) const;
|
||||
virtual void do_copy(void* dest, const void* from, size_t num) const;
|
||||
virtual void do_splat(void* dest, const void* item, size_t num) const;
|
||||
virtual void do_move_forward(void* dest, const void* from, size_t num) const;
|
||||
virtual void do_move_backward(void* dest, const void* from, size_t num) const;
|
||||
virtual int do_compare(const void* lhs, const void* rhs) const;
|
||||
};
|
||||
|
||||
// SortedVector<T> can be trivially moved using memcpy() because moving does not
|
||||
// require any change to the underlying SharedBuffer contents or reference count.
|
||||
template<typename T> struct trait_trivial_move<SortedVector<T> > { enum { value = true }; };
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No user serviceable parts from here...
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<class TYPE> inline
|
||||
SortedVector<TYPE>::SortedVector()
|
||||
: SortedVectorImpl(sizeof(TYPE),
|
||||
((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
|
||||
|(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
|
||||
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0))
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
SortedVector<TYPE>::SortedVector(const SortedVector<TYPE>& rhs)
|
||||
: SortedVectorImpl(rhs) {
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
SortedVector<TYPE>::~SortedVector() {
|
||||
finish_vector();
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
|
||||
SortedVectorImpl::operator = (rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
|
||||
SortedVectorImpl::operator = (rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE* SortedVector<TYPE>::array() const {
|
||||
return static_cast<const TYPE *>(arrayImpl());
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
TYPE* SortedVector<TYPE>::editArray() {
|
||||
return static_cast<TYPE *>(editArrayImpl());
|
||||
}
|
||||
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE& SortedVector<TYPE>::operator[](size_t index) const {
|
||||
LOG_FATAL_IF(index>=size(),
|
||||
"%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
|
||||
int(index), int(size()));
|
||||
return *(array() + index);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE& SortedVector<TYPE>::itemAt(size_t index) const {
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE& SortedVector<TYPE>::top() const {
|
||||
return *(array() + size() - 1);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::add(const TYPE& item) {
|
||||
return SortedVectorImpl::add(&item);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::indexOf(const TYPE& item) const {
|
||||
return SortedVectorImpl::indexOf(&item);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
size_t SortedVector<TYPE>::orderOf(const TYPE& item) const {
|
||||
return SortedVectorImpl::orderOf(&item);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::merge(const Vector<TYPE>& vector) {
|
||||
return SortedVectorImpl::merge(reinterpret_cast<const VectorImpl&>(vector));
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::merge(const SortedVector<TYPE>& vector) {
|
||||
return SortedVectorImpl::merge(reinterpret_cast<const SortedVectorImpl&>(vector));
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::remove(const TYPE& item) {
|
||||
return SortedVectorImpl::remove(&item);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::removeItemsAt(size_t index, size_t count) {
|
||||
return VectorImpl::removeItemsAt(index, count);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_construct(void* storage, size_t num) const {
|
||||
construct_type( reinterpret_cast<TYPE*>(storage), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_destroy(void* storage, size_t num) const {
|
||||
destroy_type( reinterpret_cast<TYPE*>(storage), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
|
||||
copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
|
||||
splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
|
||||
move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
|
||||
move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
int SortedVector<TYPE>::do_compare(const void* lhs, const void* rhs) const {
|
||||
return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_SORTED_VECTOR_H
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_STOPWATCH_H
|
||||
#define ANDROID_STOPWATCH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Timers.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
class StopWatch
|
||||
{
|
||||
public:
|
||||
StopWatch( const char *name,
|
||||
int clock = SYSTEM_TIME_MONOTONIC,
|
||||
uint32_t flags = 0);
|
||||
~StopWatch();
|
||||
|
||||
const char* name() const;
|
||||
nsecs_t lap();
|
||||
nsecs_t elapsedTime() const;
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
const char* mName;
|
||||
int mClock;
|
||||
uint32_t mFlags;
|
||||
|
||||
struct lap_t {
|
||||
nsecs_t soFar;
|
||||
nsecs_t thisLap;
|
||||
};
|
||||
|
||||
nsecs_t mStartTime;
|
||||
lap_t mLaps[8];
|
||||
int mNumLaps;
|
||||
};
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_STOPWATCH_H
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_STRING16_H
|
||||
#define ANDROID_STRING16_H
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/SharedBuffer.h>
|
||||
#include <utils/Unicode.h>
|
||||
#include <utils/TypeHelpers.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
extern "C" {
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class String8;
|
||||
class TextOutput;
|
||||
|
||||
//! This is a string holding UTF-16 characters.
|
||||
class String16
|
||||
{
|
||||
public:
|
||||
/* use String16(StaticLinkage) if you're statically linking against
|
||||
* libutils and declaring an empty static String16, e.g.:
|
||||
*
|
||||
* static String16 sAStaticEmptyString(String16::kEmptyString);
|
||||
* static String16 sAnotherStaticEmptyString(sAStaticEmptyString);
|
||||
*/
|
||||
enum StaticLinkage { kEmptyString };
|
||||
|
||||
String16();
|
||||
explicit String16(StaticLinkage);
|
||||
String16(const String16& o);
|
||||
String16(const String16& o,
|
||||
size_t len,
|
||||
size_t begin=0);
|
||||
explicit String16(const char16_t* o);
|
||||
explicit String16(const char16_t* o, size_t len);
|
||||
explicit String16(const String8& o);
|
||||
explicit String16(const char* o);
|
||||
explicit String16(const char* o, size_t len);
|
||||
|
||||
~String16();
|
||||
|
||||
inline const char16_t* string() const;
|
||||
inline size_t size() const;
|
||||
|
||||
inline const SharedBuffer* sharedBuffer() const;
|
||||
|
||||
void setTo(const String16& other);
|
||||
status_t setTo(const char16_t* other);
|
||||
status_t setTo(const char16_t* other, size_t len);
|
||||
status_t setTo(const String16& other,
|
||||
size_t len,
|
||||
size_t begin=0);
|
||||
|
||||
status_t append(const String16& other);
|
||||
status_t append(const char16_t* other, size_t len);
|
||||
|
||||
inline String16& operator=(const String16& other);
|
||||
|
||||
inline String16& operator+=(const String16& other);
|
||||
inline String16 operator+(const String16& other) const;
|
||||
|
||||
status_t insert(size_t pos, const char16_t* chrs);
|
||||
status_t insert(size_t pos,
|
||||
const char16_t* chrs, size_t len);
|
||||
|
||||
ssize_t findFirst(char16_t c) const;
|
||||
ssize_t findLast(char16_t c) const;
|
||||
|
||||
bool startsWith(const String16& prefix) const;
|
||||
bool startsWith(const char16_t* prefix) const;
|
||||
|
||||
status_t makeLower();
|
||||
|
||||
status_t replaceAll(char16_t replaceThis,
|
||||
char16_t withThis);
|
||||
|
||||
status_t remove(size_t len, size_t begin=0);
|
||||
|
||||
inline int compare(const String16& other) const;
|
||||
|
||||
inline bool operator<(const String16& other) const;
|
||||
inline bool operator<=(const String16& other) const;
|
||||
inline bool operator==(const String16& other) const;
|
||||
inline bool operator!=(const String16& other) const;
|
||||
inline bool operator>=(const String16& other) const;
|
||||
inline bool operator>(const String16& other) const;
|
||||
|
||||
inline bool operator<(const char16_t* other) const;
|
||||
inline bool operator<=(const char16_t* other) const;
|
||||
inline bool operator==(const char16_t* other) const;
|
||||
inline bool operator!=(const char16_t* other) const;
|
||||
inline bool operator>=(const char16_t* other) const;
|
||||
inline bool operator>(const char16_t* other) const;
|
||||
|
||||
inline operator const char16_t*() const;
|
||||
|
||||
private:
|
||||
const char16_t* mString;
|
||||
};
|
||||
|
||||
// String16 can be trivially moved using memcpy() because moving does not
|
||||
// require any change to the underlying SharedBuffer contents or reference count.
|
||||
ANDROID_TRIVIAL_MOVE_TRAIT(String16)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No user servicable parts below.
|
||||
|
||||
inline int compare_type(const String16& lhs, const String16& rhs)
|
||||
{
|
||||
return lhs.compare(rhs);
|
||||
}
|
||||
|
||||
inline int strictly_order_type(const String16& lhs, const String16& rhs)
|
||||
{
|
||||
return compare_type(lhs, rhs) < 0;
|
||||
}
|
||||
|
||||
inline const char16_t* String16::string() const
|
||||
{
|
||||
return mString;
|
||||
}
|
||||
|
||||
inline size_t String16::size() const
|
||||
{
|
||||
return SharedBuffer::sizeFromData(mString)/sizeof(char16_t)-1;
|
||||
}
|
||||
|
||||
inline const SharedBuffer* String16::sharedBuffer() const
|
||||
{
|
||||
return SharedBuffer::bufferFromData(mString);
|
||||
}
|
||||
|
||||
inline String16& String16::operator=(const String16& other)
|
||||
{
|
||||
setTo(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline String16& String16::operator+=(const String16& other)
|
||||
{
|
||||
append(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline String16 String16::operator+(const String16& other) const
|
||||
{
|
||||
String16 tmp(*this);
|
||||
tmp += other;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline int String16::compare(const String16& other) const
|
||||
{
|
||||
return strzcmp16(mString, size(), other.mString, other.size());
|
||||
}
|
||||
|
||||
inline bool String16::operator<(const String16& other) const
|
||||
{
|
||||
return strzcmp16(mString, size(), other.mString, other.size()) < 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator<=(const String16& other) const
|
||||
{
|
||||
return strzcmp16(mString, size(), other.mString, other.size()) <= 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator==(const String16& other) const
|
||||
{
|
||||
return strzcmp16(mString, size(), other.mString, other.size()) == 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator!=(const String16& other) const
|
||||
{
|
||||
return strzcmp16(mString, size(), other.mString, other.size()) != 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator>=(const String16& other) const
|
||||
{
|
||||
return strzcmp16(mString, size(), other.mString, other.size()) >= 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator>(const String16& other) const
|
||||
{
|
||||
return strzcmp16(mString, size(), other.mString, other.size()) > 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator<(const char16_t* other) const
|
||||
{
|
||||
return strcmp16(mString, other) < 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator<=(const char16_t* other) const
|
||||
{
|
||||
return strcmp16(mString, other) <= 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator==(const char16_t* other) const
|
||||
{
|
||||
return strcmp16(mString, other) == 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator!=(const char16_t* other) const
|
||||
{
|
||||
return strcmp16(mString, other) != 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator>=(const char16_t* other) const
|
||||
{
|
||||
return strcmp16(mString, other) >= 0;
|
||||
}
|
||||
|
||||
inline bool String16::operator>(const char16_t* other) const
|
||||
{
|
||||
return strcmp16(mString, other) > 0;
|
||||
}
|
||||
|
||||
inline String16::operator const char16_t*() const
|
||||
{
|
||||
return mString;
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_STRING16_H
|
||||
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_STRING8_H
|
||||
#define ANDROID_STRING8_H
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/SharedBuffer.h>
|
||||
#include <utils/Unicode.h>
|
||||
#include <utils/TypeHelpers.h>
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
#include <stdarg.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
class String16;
|
||||
class TextOutput;
|
||||
|
||||
//! This is a string holding UTF-8 characters. Does not allow the value more
|
||||
// than 0x10FFFF, which is not valid unicode codepoint.
|
||||
class String8
|
||||
{
|
||||
public:
|
||||
/* use String8(StaticLinkage) if you're statically linking against
|
||||
* libutils and declaring an empty static String8, e.g.:
|
||||
*
|
||||
* static String8 sAStaticEmptyString(String8::kEmptyString);
|
||||
* static String8 sAnotherStaticEmptyString(sAStaticEmptyString);
|
||||
*/
|
||||
enum StaticLinkage { kEmptyString };
|
||||
|
||||
String8();
|
||||
explicit String8(StaticLinkage);
|
||||
String8(const String8& o);
|
||||
explicit String8(const char* o);
|
||||
explicit String8(const char* o, size_t numChars);
|
||||
|
||||
explicit String8(const String16& o);
|
||||
explicit String8(const char16_t* o);
|
||||
explicit String8(const char16_t* o, size_t numChars);
|
||||
explicit String8(const char32_t* o);
|
||||
explicit String8(const char32_t* o, size_t numChars);
|
||||
~String8();
|
||||
|
||||
static inline const String8 empty();
|
||||
|
||||
static String8 format(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
|
||||
static String8 formatV(const char* fmt, va_list args);
|
||||
|
||||
inline const char* string() const;
|
||||
inline size_t size() const;
|
||||
inline size_t length() const;
|
||||
inline size_t bytes() const;
|
||||
inline bool isEmpty() const;
|
||||
|
||||
inline const SharedBuffer* sharedBuffer() const;
|
||||
|
||||
void clear();
|
||||
|
||||
void setTo(const String8& other);
|
||||
status_t setTo(const char* other);
|
||||
status_t setTo(const char* other, size_t numChars);
|
||||
status_t setTo(const char16_t* other, size_t numChars);
|
||||
status_t setTo(const char32_t* other,
|
||||
size_t length);
|
||||
|
||||
status_t append(const String8& other);
|
||||
status_t append(const char* other);
|
||||
status_t append(const char* other, size_t numChars);
|
||||
|
||||
status_t appendFormat(const char* fmt, ...)
|
||||
__attribute__((format (printf, 2, 3)));
|
||||
status_t appendFormatV(const char* fmt, va_list args);
|
||||
|
||||
// Note that this function takes O(N) time to calculate the value.
|
||||
// No cache value is stored.
|
||||
size_t getUtf32Length() const;
|
||||
int32_t getUtf32At(size_t index,
|
||||
size_t *next_index) const;
|
||||
void getUtf32(char32_t* dst) const;
|
||||
|
||||
inline String8& operator=(const String8& other);
|
||||
inline String8& operator=(const char* other);
|
||||
|
||||
inline String8& operator+=(const String8& other);
|
||||
inline String8 operator+(const String8& other) const;
|
||||
|
||||
inline String8& operator+=(const char* other);
|
||||
inline String8 operator+(const char* other) const;
|
||||
|
||||
inline int compare(const String8& other) const;
|
||||
|
||||
inline bool operator<(const String8& other) const;
|
||||
inline bool operator<=(const String8& other) const;
|
||||
inline bool operator==(const String8& other) const;
|
||||
inline bool operator!=(const String8& other) const;
|
||||
inline bool operator>=(const String8& other) const;
|
||||
inline bool operator>(const String8& other) const;
|
||||
|
||||
inline bool operator<(const char* other) const;
|
||||
inline bool operator<=(const char* other) const;
|
||||
inline bool operator==(const char* other) const;
|
||||
inline bool operator!=(const char* other) const;
|
||||
inline bool operator>=(const char* other) const;
|
||||
inline bool operator>(const char* other) const;
|
||||
|
||||
inline operator const char*() const;
|
||||
|
||||
char* lockBuffer(size_t size);
|
||||
void unlockBuffer();
|
||||
status_t unlockBuffer(size_t size);
|
||||
|
||||
// return the index of the first byte of other in this at or after
|
||||
// start, or -1 if not found
|
||||
ssize_t find(const char* other, size_t start = 0) const;
|
||||
|
||||
// return true if this string contains the specified substring
|
||||
inline bool contains(const char* other) const;
|
||||
|
||||
// removes all occurrence of the specified substring
|
||||
// returns true if any were found and removed
|
||||
bool removeAll(const char* other);
|
||||
|
||||
void toLower();
|
||||
void toLower(size_t start, size_t numChars);
|
||||
void toUpper();
|
||||
void toUpper(size_t start, size_t numChars);
|
||||
|
||||
|
||||
/*
|
||||
* These methods operate on the string as if it were a path name.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the filename field to a specific value.
|
||||
*
|
||||
* Normalizes the filename, removing a trailing '/' if present.
|
||||
*/
|
||||
void setPathName(const char* name);
|
||||
void setPathName(const char* name, size_t numChars);
|
||||
|
||||
/*
|
||||
* Get just the filename component.
|
||||
*
|
||||
* "/tmp/foo/bar.c" --> "bar.c"
|
||||
*/
|
||||
String8 getPathLeaf(void) const;
|
||||
|
||||
/*
|
||||
* Remove the last (file name) component, leaving just the directory
|
||||
* name.
|
||||
*
|
||||
* "/tmp/foo/bar.c" --> "/tmp/foo"
|
||||
* "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX
|
||||
* "bar.c" --> ""
|
||||
*/
|
||||
String8 getPathDir(void) const;
|
||||
|
||||
/*
|
||||
* Retrieve the front (root dir) component. Optionally also return the
|
||||
* remaining components.
|
||||
*
|
||||
* "/tmp/foo/bar.c" --> "tmp" (remain = "foo/bar.c")
|
||||
* "/tmp" --> "tmp" (remain = "")
|
||||
* "bar.c" --> "bar.c" (remain = "")
|
||||
*/
|
||||
String8 walkPath(String8* outRemains = NULL) const;
|
||||
|
||||
/*
|
||||
* Return the filename extension. This is the last '.' and any number
|
||||
* of characters that follow it. The '.' is included in case we
|
||||
* decide to expand our definition of what constitutes an extension.
|
||||
*
|
||||
* "/tmp/foo/bar.c" --> ".c"
|
||||
* "/tmp" --> ""
|
||||
* "/tmp/foo.bar/baz" --> ""
|
||||
* "foo.jpeg" --> ".jpeg"
|
||||
* "foo." --> ""
|
||||
*/
|
||||
String8 getPathExtension(void) const;
|
||||
|
||||
/*
|
||||
* Return the path without the extension. Rules for what constitutes
|
||||
* an extension are described in the comment for getPathExtension().
|
||||
*
|
||||
* "/tmp/foo/bar.c" --> "/tmp/foo/bar"
|
||||
*/
|
||||
String8 getBasePath(void) const;
|
||||
|
||||
/*
|
||||
* Add a component to the pathname. We guarantee that there is
|
||||
* exactly one path separator between the old path and the new.
|
||||
* If there is no existing name, we just copy the new name in.
|
||||
*
|
||||
* If leaf is a fully qualified path (i.e. starts with '/', it
|
||||
* replaces whatever was there before.
|
||||
*/
|
||||
String8& appendPath(const char* leaf);
|
||||
String8& appendPath(const String8& leaf) { return appendPath(leaf.string()); }
|
||||
|
||||
/*
|
||||
* Like appendPath(), but does not affect this string. Returns a new one instead.
|
||||
*/
|
||||
String8 appendPathCopy(const char* leaf) const
|
||||
{ String8 p(*this); p.appendPath(leaf); return p; }
|
||||
String8 appendPathCopy(const String8& leaf) const { return appendPathCopy(leaf.string()); }
|
||||
|
||||
/*
|
||||
* Converts all separators in this string to /, the default path separator.
|
||||
*
|
||||
* If the default OS separator is backslash, this converts all
|
||||
* backslashes to slashes, in-place. Otherwise it does nothing.
|
||||
* Returns self.
|
||||
*/
|
||||
String8& convertToResPath();
|
||||
|
||||
private:
|
||||
status_t real_append(const char* other, size_t numChars);
|
||||
char* find_extension(void) const;
|
||||
|
||||
const char* mString;
|
||||
};
|
||||
|
||||
// String8 can be trivially moved using memcpy() because moving does not
|
||||
// require any change to the underlying SharedBuffer contents or reference count.
|
||||
ANDROID_TRIVIAL_MOVE_TRAIT(String8)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No user servicable parts below.
|
||||
|
||||
inline int compare_type(const String8& lhs, const String8& rhs)
|
||||
{
|
||||
return lhs.compare(rhs);
|
||||
}
|
||||
|
||||
inline int strictly_order_type(const String8& lhs, const String8& rhs)
|
||||
{
|
||||
return compare_type(lhs, rhs) < 0;
|
||||
}
|
||||
|
||||
inline const String8 String8::empty() {
|
||||
return String8();
|
||||
}
|
||||
|
||||
inline const char* String8::string() const
|
||||
{
|
||||
return mString;
|
||||
}
|
||||
|
||||
inline size_t String8::length() const
|
||||
{
|
||||
return SharedBuffer::sizeFromData(mString)-1;
|
||||
}
|
||||
|
||||
inline size_t String8::size() const
|
||||
{
|
||||
return length();
|
||||
}
|
||||
|
||||
inline bool String8::isEmpty() const
|
||||
{
|
||||
return length() == 0;
|
||||
}
|
||||
|
||||
inline size_t String8::bytes() const
|
||||
{
|
||||
return SharedBuffer::sizeFromData(mString)-1;
|
||||
}
|
||||
|
||||
inline const SharedBuffer* String8::sharedBuffer() const
|
||||
{
|
||||
return SharedBuffer::bufferFromData(mString);
|
||||
}
|
||||
|
||||
inline bool String8::contains(const char* other) const
|
||||
{
|
||||
return find(other) >= 0;
|
||||
}
|
||||
|
||||
inline String8& String8::operator=(const String8& other)
|
||||
{
|
||||
setTo(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline String8& String8::operator=(const char* other)
|
||||
{
|
||||
setTo(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline String8& String8::operator+=(const String8& other)
|
||||
{
|
||||
append(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline String8 String8::operator+(const String8& other) const
|
||||
{
|
||||
String8 tmp(*this);
|
||||
tmp += other;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline String8& String8::operator+=(const char* other)
|
||||
{
|
||||
append(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline String8 String8::operator+(const char* other) const
|
||||
{
|
||||
String8 tmp(*this);
|
||||
tmp += other;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline int String8::compare(const String8& other) const
|
||||
{
|
||||
return strcmp(mString, other.mString);
|
||||
}
|
||||
|
||||
inline bool String8::operator<(const String8& other) const
|
||||
{
|
||||
return strcmp(mString, other.mString) < 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator<=(const String8& other) const
|
||||
{
|
||||
return strcmp(mString, other.mString) <= 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator==(const String8& other) const
|
||||
{
|
||||
return strcmp(mString, other.mString) == 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator!=(const String8& other) const
|
||||
{
|
||||
return strcmp(mString, other.mString) != 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator>=(const String8& other) const
|
||||
{
|
||||
return strcmp(mString, other.mString) >= 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator>(const String8& other) const
|
||||
{
|
||||
return strcmp(mString, other.mString) > 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator<(const char* other) const
|
||||
{
|
||||
return strcmp(mString, other) < 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator<=(const char* other) const
|
||||
{
|
||||
return strcmp(mString, other) <= 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator==(const char* other) const
|
||||
{
|
||||
return strcmp(mString, other) == 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator!=(const char* other) const
|
||||
{
|
||||
return strcmp(mString, other) != 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator>=(const char* other) const
|
||||
{
|
||||
return strcmp(mString, other) >= 0;
|
||||
}
|
||||
|
||||
inline bool String8::operator>(const char* other) const
|
||||
{
|
||||
return strcmp(mString, other) > 0;
|
||||
}
|
||||
|
||||
inline String8::operator const char*() const
|
||||
{
|
||||
return mString;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_STRING8_H
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_STRONG_POINTER_H
|
||||
#define ANDROID_STRONG_POINTER_H
|
||||
|
||||
#include <cutils/atomic.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
|
||||
template<typename T> class wp;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define COMPARE(_op_) \
|
||||
inline bool operator _op_ (const sp<T>& o) const { \
|
||||
return m_ptr _op_ o.m_ptr; \
|
||||
} \
|
||||
inline bool operator _op_ (const T* o) const { \
|
||||
return m_ptr _op_ o; \
|
||||
} \
|
||||
template<typename U> \
|
||||
inline bool operator _op_ (const sp<U>& o) const { \
|
||||
return m_ptr _op_ o.m_ptr; \
|
||||
} \
|
||||
template<typename U> \
|
||||
inline bool operator _op_ (const U* o) const { \
|
||||
return m_ptr _op_ o; \
|
||||
} \
|
||||
inline bool operator _op_ (const wp<T>& o) const { \
|
||||
return m_ptr _op_ o.m_ptr; \
|
||||
} \
|
||||
template<typename U> \
|
||||
inline bool operator _op_ (const wp<U>& o) const { \
|
||||
return m_ptr _op_ o.m_ptr; \
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
class sp {
|
||||
public:
|
||||
inline sp() : m_ptr(0) { }
|
||||
|
||||
sp(T* other);
|
||||
sp(const sp<T>& other);
|
||||
template<typename U> sp(U* other);
|
||||
template<typename U> sp(const sp<U>& other);
|
||||
|
||||
~sp();
|
||||
|
||||
// Assignment
|
||||
|
||||
sp& operator = (T* other);
|
||||
sp& operator = (const sp<T>& other);
|
||||
|
||||
template<typename U> sp& operator = (const sp<U>& other);
|
||||
template<typename U> sp& operator = (U* other);
|
||||
|
||||
//! Special optimization for use by ProcessState (and nobody else).
|
||||
void force_set(T* other);
|
||||
|
||||
// Reset
|
||||
|
||||
void clear();
|
||||
|
||||
// Accessors
|
||||
|
||||
inline T& operator* () const { return *m_ptr; }
|
||||
inline T* operator-> () const { return m_ptr; }
|
||||
inline T* get() const { return m_ptr; }
|
||||
|
||||
// Operators
|
||||
|
||||
COMPARE(==)
|
||||
COMPARE(!=)
|
||||
COMPARE(>)
|
||||
COMPARE(<)
|
||||
COMPARE(<=)
|
||||
COMPARE(>=)
|
||||
|
||||
private:
|
||||
template<typename Y> friend class sp;
|
||||
template<typename Y> friend class wp;
|
||||
void set_pointer(T* ptr);
|
||||
T* m_ptr;
|
||||
};
|
||||
|
||||
#undef COMPARE
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No user serviceable parts below here.
|
||||
|
||||
template<typename T>
|
||||
sp<T>::sp(T* other)
|
||||
: m_ptr(other) {
|
||||
if (other)
|
||||
other->incStrong(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
sp<T>::sp(const sp<T>& other)
|
||||
: m_ptr(other.m_ptr) {
|
||||
if (m_ptr)
|
||||
m_ptr->incStrong(this);
|
||||
}
|
||||
|
||||
template<typename T> template<typename U>
|
||||
sp<T>::sp(U* other)
|
||||
: m_ptr(other) {
|
||||
if (other)
|
||||
((T*) other)->incStrong(this);
|
||||
}
|
||||
|
||||
template<typename T> template<typename U>
|
||||
sp<T>::sp(const sp<U>& other)
|
||||
: m_ptr(other.m_ptr) {
|
||||
if (m_ptr)
|
||||
m_ptr->incStrong(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
sp<T>::~sp() {
|
||||
if (m_ptr)
|
||||
m_ptr->decStrong(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
sp<T>& sp<T>::operator =(const sp<T>& other) {
|
||||
T* otherPtr(other.m_ptr);
|
||||
if (otherPtr)
|
||||
otherPtr->incStrong(this);
|
||||
if (m_ptr)
|
||||
m_ptr->decStrong(this);
|
||||
m_ptr = otherPtr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
sp<T>& sp<T>::operator =(T* other) {
|
||||
if (other)
|
||||
other->incStrong(this);
|
||||
if (m_ptr)
|
||||
m_ptr->decStrong(this);
|
||||
m_ptr = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> template<typename U>
|
||||
sp<T>& sp<T>::operator =(const sp<U>& other) {
|
||||
T* otherPtr(other.m_ptr);
|
||||
if (otherPtr)
|
||||
otherPtr->incStrong(this);
|
||||
if (m_ptr)
|
||||
m_ptr->decStrong(this);
|
||||
m_ptr = otherPtr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> template<typename U>
|
||||
sp<T>& sp<T>::operator =(U* other) {
|
||||
if (other)
|
||||
((T*) other)->incStrong(this);
|
||||
if (m_ptr)
|
||||
m_ptr->decStrong(this);
|
||||
m_ptr = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void sp<T>::force_set(T* other) {
|
||||
other->forceIncStrong(this);
|
||||
m_ptr = other;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void sp<T>::clear() {
|
||||
if (m_ptr) {
|
||||
m_ptr->decStrong(this);
|
||||
m_ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void sp<T>::set_pointer(T* ptr) {
|
||||
m_ptr = ptr;
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_STRONG_POINTER_H
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2008 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_UTILS_SYSTEMCLOCK_H
|
||||
#define ANDROID_UTILS_SYSTEMCLOCK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
int64_t uptimeMillis();
|
||||
int64_t elapsedRealtime();
|
||||
int64_t elapsedRealtimeNano();
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_UTILS_SYSTEMCLOCK_H
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 _LIBS_UTILS_THREAD_H
|
||||
#define _LIBS_UTILS_THREAD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <utils/Condition.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/Timers.h>
|
||||
#include <utils/ThreadDefs.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Thread : virtual public RefBase
|
||||
{
|
||||
public:
|
||||
// Create a Thread object, but doesn't create or start the associated
|
||||
// thread. See the run() method.
|
||||
Thread(bool canCallJava = true);
|
||||
virtual ~Thread();
|
||||
|
||||
// Start the thread in threadLoop() which needs to be implemented.
|
||||
virtual status_t run( const char* name = 0,
|
||||
int32_t priority = PRIORITY_DEFAULT,
|
||||
size_t stack = 0);
|
||||
|
||||
// Ask this object's thread to exit. This function is asynchronous, when the
|
||||
// function returns the thread might still be running. Of course, this
|
||||
// function can be called from a different thread.
|
||||
virtual void requestExit();
|
||||
|
||||
// Good place to do one-time initializations
|
||||
virtual status_t readyToRun();
|
||||
|
||||
// Call requestExit() and wait until this object's thread exits.
|
||||
// BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
|
||||
// this function from this object's thread. Will return WOULD_BLOCK in
|
||||
// that case.
|
||||
status_t requestExitAndWait();
|
||||
|
||||
// Wait until this object's thread exits. Returns immediately if not yet running.
|
||||
// Do not call from this object's thread; will return WOULD_BLOCK in that case.
|
||||
status_t join();
|
||||
|
||||
// Indicates whether this thread is running or not.
|
||||
bool isRunning() const;
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
// Return the thread's kernel ID, same as the thread itself calling gettid(),
|
||||
// or -1 if the thread is not running.
|
||||
pid_t getTid() const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// exitPending() returns true if requestExit() has been called.
|
||||
bool exitPending() const;
|
||||
|
||||
private:
|
||||
// Derived class must implement threadLoop(). The thread starts its life
|
||||
// here. There are two ways of using the Thread object:
|
||||
// 1) loop: if threadLoop() returns true, it will be called again if
|
||||
// requestExit() wasn't called.
|
||||
// 2) once: if threadLoop() returns false, the thread will exit upon return.
|
||||
virtual bool threadLoop() = 0;
|
||||
|
||||
private:
|
||||
Thread& operator=(const Thread&);
|
||||
static int _threadLoop(void* user);
|
||||
const bool mCanCallJava;
|
||||
// always hold mLock when reading or writing
|
||||
thread_id_t mThread;
|
||||
mutable Mutex mLock;
|
||||
Condition mThreadExitedCondition;
|
||||
status_t mStatus;
|
||||
// note that all accesses of mExitPending and mRunning need to hold mLock
|
||||
volatile bool mExitPending;
|
||||
volatile bool mRunning;
|
||||
sp<Thread> mHoldSelf;
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
// legacy for debugging, not used by getTid() as it is set by the child thread
|
||||
// and so is not initialized until the child reaches that point
|
||||
pid_t mTid;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
#endif // _LIBS_UTILS_THREAD_H
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 _LIBS_UTILS_THREAD_DEFS_H
|
||||
#define _LIBS_UTILS_THREAD_DEFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <system/graphics.h>
|
||||
#include <system/thread_defs.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C API
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* android_thread_id_t;
|
||||
|
||||
typedef int (*android_thread_func_t)(void*);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C++ API
|
||||
#ifdef __cplusplus
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
typedef android_thread_id_t thread_id_t;
|
||||
typedef android_thread_func_t thread_func_t;
|
||||
|
||||
enum {
|
||||
PRIORITY_LOWEST = ANDROID_PRIORITY_LOWEST,
|
||||
PRIORITY_BACKGROUND = ANDROID_PRIORITY_BACKGROUND,
|
||||
PRIORITY_NORMAL = ANDROID_PRIORITY_NORMAL,
|
||||
PRIORITY_FOREGROUND = ANDROID_PRIORITY_FOREGROUND,
|
||||
PRIORITY_DISPLAY = ANDROID_PRIORITY_DISPLAY,
|
||||
PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
|
||||
PRIORITY_AUDIO = ANDROID_PRIORITY_AUDIO,
|
||||
PRIORITY_URGENT_AUDIO = ANDROID_PRIORITY_URGENT_AUDIO,
|
||||
PRIORITY_HIGHEST = ANDROID_PRIORITY_HIGHEST,
|
||||
PRIORITY_DEFAULT = ANDROID_PRIORITY_DEFAULT,
|
||||
PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
|
||||
PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
#endif // __cplusplus
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // _LIBS_UTILS_THREAD_DEFS_H
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Timer functions.
|
||||
//
|
||||
#ifndef _LIBS_UTILS_TIMERS_H
|
||||
#define _LIBS_UTILS_TIMERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <utils/Compat.h>
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// C API
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int64_t nsecs_t; // nano-seconds
|
||||
|
||||
static CONSTEXPR inline nsecs_t seconds_to_nanoseconds(nsecs_t secs)
|
||||
{
|
||||
return secs*1000000000;
|
||||
}
|
||||
|
||||
static CONSTEXPR inline nsecs_t milliseconds_to_nanoseconds(nsecs_t secs)
|
||||
{
|
||||
return secs*1000000;
|
||||
}
|
||||
|
||||
static CONSTEXPR inline nsecs_t microseconds_to_nanoseconds(nsecs_t secs)
|
||||
{
|
||||
return secs*1000;
|
||||
}
|
||||
|
||||
static CONSTEXPR inline nsecs_t nanoseconds_to_seconds(nsecs_t secs)
|
||||
{
|
||||
return secs/1000000000;
|
||||
}
|
||||
|
||||
static CONSTEXPR inline nsecs_t nanoseconds_to_milliseconds(nsecs_t secs)
|
||||
{
|
||||
return secs/1000000;
|
||||
}
|
||||
|
||||
static CONSTEXPR inline nsecs_t nanoseconds_to_microseconds(nsecs_t secs)
|
||||
{
|
||||
return secs/1000;
|
||||
}
|
||||
|
||||
static CONSTEXPR inline nsecs_t s2ns(nsecs_t v) {return seconds_to_nanoseconds(v);}
|
||||
static CONSTEXPR inline nsecs_t ms2ns(nsecs_t v) {return milliseconds_to_nanoseconds(v);}
|
||||
static CONSTEXPR inline nsecs_t us2ns(nsecs_t v) {return microseconds_to_nanoseconds(v);}
|
||||
static CONSTEXPR inline nsecs_t ns2s(nsecs_t v) {return nanoseconds_to_seconds(v);}
|
||||
static CONSTEXPR inline nsecs_t ns2ms(nsecs_t v) {return nanoseconds_to_milliseconds(v);}
|
||||
static CONSTEXPR inline nsecs_t ns2us(nsecs_t v) {return nanoseconds_to_microseconds(v);}
|
||||
|
||||
static CONSTEXPR inline nsecs_t seconds(nsecs_t v) { return s2ns(v); }
|
||||
static CONSTEXPR inline nsecs_t milliseconds(nsecs_t v) { return ms2ns(v); }
|
||||
static CONSTEXPR inline nsecs_t microseconds(nsecs_t v) { return us2ns(v); }
|
||||
|
||||
enum {
|
||||
SYSTEM_TIME_REALTIME = 0, // system-wide realtime clock
|
||||
SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point
|
||||
SYSTEM_TIME_PROCESS = 2, // high-resolution per-process clock
|
||||
SYSTEM_TIME_THREAD = 3, // high-resolution per-thread clock
|
||||
SYSTEM_TIME_BOOTTIME = 4 // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time
|
||||
};
|
||||
|
||||
// return the system-time according to the specified clock
|
||||
#ifdef __cplusplus
|
||||
nsecs_t systemTime(int clock = SYSTEM_TIME_MONOTONIC);
|
||||
#else
|
||||
nsecs_t systemTime(int clock);
|
||||
#endif // def __cplusplus
|
||||
|
||||
/**
|
||||
* Returns the number of milliseconds to wait between the reference time and the timeout time.
|
||||
* If the timeout is in the past relative to the reference time, returns 0.
|
||||
* If the timeout is more than INT_MAX milliseconds in the future relative to the reference time,
|
||||
* such as when timeoutTime == LLONG_MAX, returns -1 to indicate an infinite timeout delay.
|
||||
* Otherwise, returns the difference between the reference time and timeout time
|
||||
* rounded up to the next millisecond.
|
||||
*/
|
||||
int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // _LIBS_UTILS_TIMERS_H
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 _UTILS_TOKENIZER_H
|
||||
#define _UTILS_TOKENIZER_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/FileMap.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* A simple tokenizer for loading and parsing ASCII text files line by line.
|
||||
*/
|
||||
class Tokenizer {
|
||||
Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
|
||||
bool ownBuffer, size_t length);
|
||||
|
||||
public:
|
||||
~Tokenizer();
|
||||
|
||||
/**
|
||||
* Opens a file and maps it into memory.
|
||||
*
|
||||
* Returns NO_ERROR and a tokenizer for the file, if successful.
|
||||
* Otherwise returns an error and sets outTokenizer to NULL.
|
||||
*/
|
||||
static status_t open(const String8& filename, Tokenizer** outTokenizer);
|
||||
|
||||
/**
|
||||
* Prepares to tokenize the contents of a string.
|
||||
*
|
||||
* Returns NO_ERROR and a tokenizer for the string, if successful.
|
||||
* Otherwise returns an error and sets outTokenizer to NULL.
|
||||
*/
|
||||
static status_t fromContents(const String8& filename,
|
||||
const char* contents, Tokenizer** outTokenizer);
|
||||
|
||||
/**
|
||||
* Returns true if at the end of the file.
|
||||
*/
|
||||
inline bool isEof() const { return mCurrent == getEnd(); }
|
||||
|
||||
/**
|
||||
* Returns true if at the end of the line or end of the file.
|
||||
*/
|
||||
inline bool isEol() const { return isEof() || *mCurrent == '\n'; }
|
||||
|
||||
/**
|
||||
* Gets the name of the file.
|
||||
*/
|
||||
inline String8 getFilename() const { return mFilename; }
|
||||
|
||||
/**
|
||||
* Gets a 1-based line number index for the current position.
|
||||
*/
|
||||
inline int32_t getLineNumber() const { return mLineNumber; }
|
||||
|
||||
/**
|
||||
* Formats a location string consisting of the filename and current line number.
|
||||
* Returns a string like "MyFile.txt:33".
|
||||
*/
|
||||
String8 getLocation() const;
|
||||
|
||||
/**
|
||||
* Gets the character at the current position.
|
||||
* Returns null at end of file.
|
||||
*/
|
||||
inline char peekChar() const { return isEof() ? '\0' : *mCurrent; }
|
||||
|
||||
/**
|
||||
* Gets the remainder of the current line as a string, excluding the newline character.
|
||||
*/
|
||||
String8 peekRemainderOfLine() const;
|
||||
|
||||
/**
|
||||
* Gets the character at the current position and advances past it.
|
||||
* Returns null at end of file.
|
||||
*/
|
||||
inline char nextChar() { return isEof() ? '\0' : *(mCurrent++); }
|
||||
|
||||
/**
|
||||
* Gets the next token on this line stopping at the specified delimiters
|
||||
* or the end of the line whichever comes first and advances past it.
|
||||
* Also stops at embedded nulls.
|
||||
* Returns the token or an empty string if the current character is a delimiter
|
||||
* or is at the end of the line.
|
||||
*/
|
||||
String8 nextToken(const char* delimiters);
|
||||
|
||||
/**
|
||||
* Advances to the next line.
|
||||
* Does nothing if already at the end of the file.
|
||||
*/
|
||||
void nextLine();
|
||||
|
||||
/**
|
||||
* Skips over the specified delimiters in the line.
|
||||
* Also skips embedded nulls.
|
||||
*/
|
||||
void skipDelimiters(const char* delimiters);
|
||||
|
||||
private:
|
||||
Tokenizer(const Tokenizer& other); // not copyable
|
||||
|
||||
String8 mFilename;
|
||||
FileMap* mFileMap;
|
||||
char* mBuffer;
|
||||
bool mOwnBuffer;
|
||||
size_t mLength;
|
||||
|
||||
const char* mCurrent;
|
||||
int32_t mLineNumber;
|
||||
|
||||
inline const char* getEnd() const { return mBuffer + mLength; }
|
||||
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _UTILS_TOKENIZER_H
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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_TRACE_H
|
||||
#define ANDROID_TRACE_H
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cutils/compiler.h>
|
||||
#include <utils/threads.h>
|
||||
#include <cutils/trace.h>
|
||||
|
||||
// See <cutils/trace.h> for more ATRACE_* macros.
|
||||
|
||||
// ATRACE_NAME traces the beginning and end of the current scope. To trace
|
||||
// the correct start and end times this macro should be declared first in the
|
||||
// scope body.
|
||||
#define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name)
|
||||
// ATRACE_CALL is an ATRACE_NAME that uses the current function name.
|
||||
#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
|
||||
|
||||
namespace android {
|
||||
|
||||
class ScopedTrace {
|
||||
public:
|
||||
inline ScopedTrace(uint64_t tag, const char* name)
|
||||
: mTag(tag) {
|
||||
atrace_begin(mTag,name);
|
||||
}
|
||||
|
||||
inline ~ScopedTrace() {
|
||||
atrace_end(mTag);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t mTag;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#else // HAVE_ANDROID_OS
|
||||
|
||||
#define ATRACE_NAME(...)
|
||||
#define ATRACE_CALL()
|
||||
|
||||
#endif // HAVE_ANDROID_OS
|
||||
|
||||
#endif // ANDROID_TRACE_H
|
||||
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_TYPE_HELPERS_H
|
||||
#define ANDROID_TYPE_HELPERS_H
|
||||
|
||||
#include <new>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* Types traits
|
||||
*/
|
||||
|
||||
template <typename T> struct trait_trivial_ctor { enum { value = false }; };
|
||||
template <typename T> struct trait_trivial_dtor { enum { value = false }; };
|
||||
template <typename T> struct trait_trivial_copy { enum { value = false }; };
|
||||
template <typename T> struct trait_trivial_move { enum { value = false }; };
|
||||
template <typename T> struct trait_pointer { enum { value = false }; };
|
||||
template <typename T> struct trait_pointer<T*> { enum { value = true }; };
|
||||
|
||||
template <typename TYPE>
|
||||
struct traits {
|
||||
enum {
|
||||
// whether this type is a pointer
|
||||
is_pointer = trait_pointer<TYPE>::value,
|
||||
// whether this type's constructor is a no-op
|
||||
has_trivial_ctor = is_pointer || trait_trivial_ctor<TYPE>::value,
|
||||
// whether this type's destructor is a no-op
|
||||
has_trivial_dtor = is_pointer || trait_trivial_dtor<TYPE>::value,
|
||||
// whether this type type can be copy-constructed with memcpy
|
||||
has_trivial_copy = is_pointer || trait_trivial_copy<TYPE>::value,
|
||||
// whether this type can be moved with memmove
|
||||
has_trivial_move = is_pointer || trait_trivial_move<TYPE>::value
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct aggregate_traits {
|
||||
enum {
|
||||
is_pointer = false,
|
||||
has_trivial_ctor =
|
||||
traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
|
||||
has_trivial_dtor =
|
||||
traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
|
||||
has_trivial_copy =
|
||||
traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
|
||||
has_trivial_move =
|
||||
traits<T>::has_trivial_move && traits<U>::has_trivial_move
|
||||
};
|
||||
};
|
||||
|
||||
#define ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
|
||||
template<> struct trait_trivial_ctor< T > { enum { value = true }; };
|
||||
|
||||
#define ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
|
||||
template<> struct trait_trivial_dtor< T > { enum { value = true }; };
|
||||
|
||||
#define ANDROID_TRIVIAL_COPY_TRAIT( T ) \
|
||||
template<> struct trait_trivial_copy< T > { enum { value = true }; };
|
||||
|
||||
#define ANDROID_TRIVIAL_MOVE_TRAIT( T ) \
|
||||
template<> struct trait_trivial_move< T > { enum { value = true }; };
|
||||
|
||||
#define ANDROID_BASIC_TYPES_TRAITS( T ) \
|
||||
ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
|
||||
ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
|
||||
ANDROID_TRIVIAL_COPY_TRAIT( T ) \
|
||||
ANDROID_TRIVIAL_MOVE_TRAIT( T )
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* basic types traits
|
||||
*/
|
||||
|
||||
ANDROID_BASIC_TYPES_TRAITS( void )
|
||||
ANDROID_BASIC_TYPES_TRAITS( bool )
|
||||
ANDROID_BASIC_TYPES_TRAITS( char )
|
||||
ANDROID_BASIC_TYPES_TRAITS( unsigned char )
|
||||
ANDROID_BASIC_TYPES_TRAITS( short )
|
||||
ANDROID_BASIC_TYPES_TRAITS( unsigned short )
|
||||
ANDROID_BASIC_TYPES_TRAITS( int )
|
||||
ANDROID_BASIC_TYPES_TRAITS( unsigned int )
|
||||
ANDROID_BASIC_TYPES_TRAITS( long )
|
||||
ANDROID_BASIC_TYPES_TRAITS( unsigned long )
|
||||
ANDROID_BASIC_TYPES_TRAITS( long long )
|
||||
ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
|
||||
ANDROID_BASIC_TYPES_TRAITS( float )
|
||||
ANDROID_BASIC_TYPES_TRAITS( double )
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
/*
|
||||
* compare and order types
|
||||
*/
|
||||
|
||||
template<typename TYPE> inline
|
||||
int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
|
||||
return (lhs < rhs) ? 1 : 0;
|
||||
}
|
||||
|
||||
template<typename TYPE> inline
|
||||
int compare_type(const TYPE& lhs, const TYPE& rhs) {
|
||||
return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
|
||||
}
|
||||
|
||||
/*
|
||||
* create, destroy, copy and move types...
|
||||
*/
|
||||
|
||||
template<typename TYPE> inline
|
||||
void construct_type(TYPE* p, size_t n) {
|
||||
if (!traits<TYPE>::has_trivial_ctor) {
|
||||
while (n--) {
|
||||
new(p++) TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TYPE> inline
|
||||
void destroy_type(TYPE* p, size_t n) {
|
||||
if (!traits<TYPE>::has_trivial_dtor) {
|
||||
while (n--) {
|
||||
p->~TYPE();
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TYPE> inline
|
||||
void copy_type(TYPE* d, const TYPE* s, size_t n) {
|
||||
if (!traits<TYPE>::has_trivial_copy) {
|
||||
while (n--) {
|
||||
new(d) TYPE(*s);
|
||||
d++, s++;
|
||||
}
|
||||
} else {
|
||||
memcpy(d,s,n*sizeof(TYPE));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TYPE> inline
|
||||
void splat_type(TYPE* where, const TYPE* what, size_t n) {
|
||||
if (!traits<TYPE>::has_trivial_copy) {
|
||||
while (n--) {
|
||||
new(where) TYPE(*what);
|
||||
where++;
|
||||
}
|
||||
} else {
|
||||
while (n--) {
|
||||
*where++ = *what;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TYPE> inline
|
||||
void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
|
||||
if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
|
||||
|| traits<TYPE>::has_trivial_move)
|
||||
{
|
||||
memmove(d,s,n*sizeof(TYPE));
|
||||
} else {
|
||||
d += n;
|
||||
s += n;
|
||||
while (n--) {
|
||||
--d, --s;
|
||||
if (!traits<TYPE>::has_trivial_copy) {
|
||||
new(d) TYPE(*s);
|
||||
} else {
|
||||
*d = *s;
|
||||
}
|
||||
if (!traits<TYPE>::has_trivial_dtor) {
|
||||
s->~TYPE();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TYPE> inline
|
||||
void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
|
||||
if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
|
||||
|| traits<TYPE>::has_trivial_move)
|
||||
{
|
||||
memmove(d,s,n*sizeof(TYPE));
|
||||
} else {
|
||||
while (n--) {
|
||||
if (!traits<TYPE>::has_trivial_copy) {
|
||||
new(d) TYPE(*s);
|
||||
} else {
|
||||
*d = *s;
|
||||
}
|
||||
if (!traits<TYPE>::has_trivial_dtor) {
|
||||
s->~TYPE();
|
||||
}
|
||||
d++, s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* a key/value pair
|
||||
*/
|
||||
|
||||
template <typename KEY, typename VALUE>
|
||||
struct key_value_pair_t {
|
||||
typedef KEY key_t;
|
||||
typedef VALUE value_t;
|
||||
|
||||
KEY key;
|
||||
VALUE value;
|
||||
key_value_pair_t() { }
|
||||
key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
|
||||
key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { }
|
||||
key_value_pair_t(const KEY& k) : key(k) { }
|
||||
inline bool operator < (const key_value_pair_t& o) const {
|
||||
return strictly_order_type(key, o.key);
|
||||
}
|
||||
inline const KEY& getKey() const {
|
||||
return key;
|
||||
}
|
||||
inline const VALUE& getValue() const {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename K, typename V>
|
||||
struct trait_trivial_ctor< key_value_pair_t<K, V> >
|
||||
{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
|
||||
template <typename K, typename V>
|
||||
struct trait_trivial_dtor< key_value_pair_t<K, V> >
|
||||
{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
|
||||
template <typename K, typename V>
|
||||
struct trait_trivial_copy< key_value_pair_t<K, V> >
|
||||
{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
|
||||
template <typename K, typename V>
|
||||
struct trait_trivial_move< key_value_pair_t<K, V> >
|
||||
{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Hash codes.
|
||||
*/
|
||||
typedef uint32_t hash_t;
|
||||
|
||||
template <typename TKey>
|
||||
hash_t hash_type(const TKey& key);
|
||||
|
||||
/* Built-in hash code specializations.
|
||||
* Assumes pointers are 32bit. */
|
||||
#define ANDROID_INT32_HASH(T) \
|
||||
template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
|
||||
#define ANDROID_INT64_HASH(T) \
|
||||
template <> inline hash_t hash_type(const T& value) { \
|
||||
return hash_t((value >> 32) ^ value); }
|
||||
#define ANDROID_REINTERPRET_HASH(T, R) \
|
||||
template <> inline hash_t hash_type(const T& value) { \
|
||||
return hash_type(*reinterpret_cast<const R*>(&value)); }
|
||||
|
||||
ANDROID_INT32_HASH(bool)
|
||||
ANDROID_INT32_HASH(int8_t)
|
||||
ANDROID_INT32_HASH(uint8_t)
|
||||
ANDROID_INT32_HASH(int16_t)
|
||||
ANDROID_INT32_HASH(uint16_t)
|
||||
ANDROID_INT32_HASH(int32_t)
|
||||
ANDROID_INT32_HASH(uint32_t)
|
||||
ANDROID_INT64_HASH(int64_t)
|
||||
ANDROID_INT64_HASH(uint64_t)
|
||||
ANDROID_REINTERPRET_HASH(float, uint32_t)
|
||||
ANDROID_REINTERPRET_HASH(double, uint64_t)
|
||||
|
||||
template <typename T> inline hash_t hash_type(T* const & value) {
|
||||
return hash_type(uintptr_t(value));
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_TYPE_HELPERS_H
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_UNICODE_H
|
||||
#define ANDROID_UNICODE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Standard string functions on char16_t strings.
|
||||
int strcmp16(const char16_t *, const char16_t *);
|
||||
int strncmp16(const char16_t *s1, const char16_t *s2, size_t n);
|
||||
size_t strlen16(const char16_t *);
|
||||
size_t strnlen16(const char16_t *, size_t);
|
||||
char16_t *strcpy16(char16_t *, const char16_t *);
|
||||
char16_t *strncpy16(char16_t *, const char16_t *, size_t);
|
||||
|
||||
// Version of comparison that supports embedded nulls.
|
||||
// This is different than strncmp() because we don't stop
|
||||
// at a nul character and consider the strings to be different
|
||||
// if the lengths are different (thus we need to supply the
|
||||
// lengths of both strings). This can also be used when
|
||||
// your string is not nul-terminated as it will have the
|
||||
// equivalent result as strcmp16 (unlike strncmp16).
|
||||
int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2);
|
||||
|
||||
// Version of strzcmp16 for comparing strings in different endianness.
|
||||
int strzcmp16_h_n(const char16_t *s1H, size_t n1, const char16_t *s2N, size_t n2);
|
||||
|
||||
// Standard string functions on char32_t strings.
|
||||
size_t strlen32(const char32_t *);
|
||||
size_t strnlen32(const char32_t *, size_t);
|
||||
|
||||
/**
|
||||
* Measure the length of a UTF-32 string in UTF-8. If the string is invalid
|
||||
* such as containing a surrogate character, -1 will be returned.
|
||||
*/
|
||||
ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len);
|
||||
|
||||
/**
|
||||
* Stores a UTF-8 string converted from "src" in "dst", if "dst_length" is not
|
||||
* large enough to store the string, the part of the "src" string is stored
|
||||
* into "dst" as much as possible. See the examples for more detail.
|
||||
* Returns the size actually used for storing the string.
|
||||
* dst" is not null-terminated when dst_len is fully used (like strncpy).
|
||||
*
|
||||
* Example 1
|
||||
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
|
||||
* "src_len" == 2
|
||||
* "dst_len" >= 7
|
||||
* ->
|
||||
* Returned value == 6
|
||||
* "dst" becomes \xE3\x81\x82\xE3\x81\x84\0
|
||||
* (note that "dst" is null-terminated)
|
||||
*
|
||||
* Example 2
|
||||
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
|
||||
* "src_len" == 2
|
||||
* "dst_len" == 5
|
||||
* ->
|
||||
* Returned value == 3
|
||||
* "dst" becomes \xE3\x81\x82\0
|
||||
* (note that "dst" is null-terminated, but \u3044 is not stored in "dst"
|
||||
* since "dst" does not have enough size to store the character)
|
||||
*
|
||||
* Example 3
|
||||
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
|
||||
* "src_len" == 2
|
||||
* "dst_len" == 6
|
||||
* ->
|
||||
* Returned value == 6
|
||||
* "dst" becomes \xE3\x81\x82\xE3\x81\x84
|
||||
* (note that "dst" is NOT null-terminated, like strncpy)
|
||||
*/
|
||||
void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len);
|
||||
|
||||
/**
|
||||
* Returns the unicode value at "index".
|
||||
* Returns -1 when the index is invalid (equals to or more than "src_len").
|
||||
* If returned value is positive, it is able to be converted to char32_t, which
|
||||
* is unsigned. Then, if "next_index" is not NULL, the next index to be used is
|
||||
* stored in "next_index". "next_index" can be NULL.
|
||||
*/
|
||||
int32_t utf32_from_utf8_at(const char *src, size_t src_len, size_t index, size_t *next_index);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the UTF-8 length of UTF-16 string "src".
|
||||
*/
|
||||
ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len);
|
||||
|
||||
/**
|
||||
* Converts a UTF-16 string to UTF-8. The destination buffer must be large
|
||||
* enough to fit the UTF-16 as measured by utf16_to_utf8_length with an added
|
||||
* NULL terminator.
|
||||
*/
|
||||
void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len);
|
||||
|
||||
/**
|
||||
* Returns the length of "src" when "src" is valid UTF-8 string.
|
||||
* Returns 0 if src is NULL or 0-length string. Returns -1 when the source
|
||||
* is an invalid string.
|
||||
*
|
||||
* This function should be used to determine whether "src" is valid UTF-8
|
||||
* characters with valid unicode codepoints. "src" must be null-terminated.
|
||||
*
|
||||
* If you are going to use other utf8_to_... functions defined in this header
|
||||
* with string which may not be valid UTF-8 with valid codepoint (form 0 to
|
||||
* 0x10FFFF), you should use this function before calling others, since the
|
||||
* other functions do not check whether the string is valid UTF-8 or not.
|
||||
*
|
||||
* If you do not care whether "src" is valid UTF-8 or not, you should use
|
||||
* strlen() as usual, which should be much faster.
|
||||
*/
|
||||
ssize_t utf8_length(const char *src);
|
||||
|
||||
/**
|
||||
* Measure the length of a UTF-32 string.
|
||||
*/
|
||||
size_t utf8_to_utf32_length(const char *src, size_t src_len);
|
||||
|
||||
/**
|
||||
* Stores a UTF-32 string converted from "src" in "dst". "dst" must be large
|
||||
* enough to store the entire converted string as measured by
|
||||
* utf8_to_utf32_length plus space for a NULL terminator.
|
||||
*/
|
||||
void utf8_to_utf32(const char* src, size_t src_len, char32_t* dst);
|
||||
|
||||
/**
|
||||
* Returns the UTF-16 length of UTF-8 string "src".
|
||||
*/
|
||||
ssize_t utf8_to_utf16_length(const uint8_t* src, size_t srcLen);
|
||||
|
||||
/**
|
||||
* Convert UTF-8 to UTF-16 including surrogate pairs.
|
||||
* Returns a pointer to the end of the string (where a null terminator might go
|
||||
* if you wanted to add one).
|
||||
*/
|
||||
char16_t* utf8_to_utf16_no_null_terminator(const uint8_t* src, size_t srcLen, char16_t* dst);
|
||||
|
||||
/**
|
||||
* Convert UTF-8 to UTF-16 including surrogate pairs. The destination buffer
|
||||
* must be large enough to hold the result as measured by utf8_to_utf16_length
|
||||
* plus an added NULL terminator.
|
||||
*/
|
||||
void utf8_to_utf16(const uint8_t* src, size_t srcLen, char16_t* dst);
|
||||
|
||||
/**
|
||||
* Like utf8_to_utf16_no_null_terminator, but you can supply a maximum length of the
|
||||
* decoded string. The decoded string will fill up to that length; if it is longer
|
||||
* the returned pointer will be to the character after dstLen.
|
||||
*/
|
||||
char16_t* utf8_to_utf16_n(const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_VECTOR_H
|
||||
#define ANDROID_VECTOR_H
|
||||
|
||||
#include <new>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <utils/VectorImpl.h>
|
||||
#include <utils/TypeHelpers.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
template <typename TYPE>
|
||||
class SortedVector;
|
||||
|
||||
/*!
|
||||
* The main templated vector class ensuring type safety
|
||||
* while making use of VectorImpl.
|
||||
* This is the class users want to use.
|
||||
*/
|
||||
|
||||
template <class TYPE>
|
||||
class Vector : private VectorImpl
|
||||
{
|
||||
public:
|
||||
typedef TYPE value_type;
|
||||
|
||||
/*!
|
||||
* Constructors and destructors
|
||||
*/
|
||||
|
||||
Vector();
|
||||
Vector(const Vector<TYPE>& rhs);
|
||||
explicit Vector(const SortedVector<TYPE>& rhs);
|
||||
virtual ~Vector();
|
||||
|
||||
/*! copy operator */
|
||||
const Vector<TYPE>& operator = (const Vector<TYPE>& rhs) const;
|
||||
Vector<TYPE>& operator = (const Vector<TYPE>& rhs);
|
||||
|
||||
const Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
|
||||
Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
|
||||
|
||||
/*
|
||||
* empty the vector
|
||||
*/
|
||||
|
||||
inline void clear() { VectorImpl::clear(); }
|
||||
|
||||
/*!
|
||||
* vector stats
|
||||
*/
|
||||
|
||||
//! returns number of items in the vector
|
||||
inline size_t size() const { return VectorImpl::size(); }
|
||||
//! returns whether or not the vector is empty
|
||||
inline bool isEmpty() const { return VectorImpl::isEmpty(); }
|
||||
//! returns how many items can be stored without reallocating the backing store
|
||||
inline size_t capacity() const { return VectorImpl::capacity(); }
|
||||
//! sets the capacity. capacity can never be reduced less than size()
|
||||
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
|
||||
|
||||
/*!
|
||||
* set the size of the vector. items are appended with the default
|
||||
* constructor, or removed from the end as needed.
|
||||
*/
|
||||
inline ssize_t resize(size_t size) { return VectorImpl::resize(size); }
|
||||
|
||||
/*!
|
||||
* C-style array access
|
||||
*/
|
||||
|
||||
//! read-only C-style access
|
||||
inline const TYPE* array() const;
|
||||
//! read-write C-style access
|
||||
TYPE* editArray();
|
||||
|
||||
/*!
|
||||
* accessors
|
||||
*/
|
||||
|
||||
//! read-only access to an item at a given index
|
||||
inline const TYPE& operator [] (size_t index) const;
|
||||
//! alternate name for operator []
|
||||
inline const TYPE& itemAt(size_t index) const;
|
||||
//! stack-usage of the vector. returns the top of the stack (last element)
|
||||
const TYPE& top() const;
|
||||
|
||||
/*!
|
||||
* modifying the array
|
||||
*/
|
||||
|
||||
//! copy-on write support, grants write access to an item
|
||||
TYPE& editItemAt(size_t index);
|
||||
//! grants right access to the top of the stack (last element)
|
||||
TYPE& editTop();
|
||||
|
||||
/*!
|
||||
* append/insert another vector
|
||||
*/
|
||||
|
||||
//! insert another vector at a given index
|
||||
ssize_t insertVectorAt(const Vector<TYPE>& vector, size_t index);
|
||||
|
||||
//! append another vector at the end of this one
|
||||
ssize_t appendVector(const Vector<TYPE>& vector);
|
||||
|
||||
|
||||
//! insert an array at a given index
|
||||
ssize_t insertArrayAt(const TYPE* array, size_t index, size_t length);
|
||||
|
||||
//! append an array at the end of this vector
|
||||
ssize_t appendArray(const TYPE* array, size_t length);
|
||||
|
||||
/*!
|
||||
* add/insert/replace items
|
||||
*/
|
||||
|
||||
//! insert one or several items initialized with their default constructor
|
||||
inline ssize_t insertAt(size_t index, size_t numItems = 1);
|
||||
//! insert one or several items initialized from a prototype item
|
||||
ssize_t insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
|
||||
//! pop the top of the stack (removes the last element). No-op if the stack's empty
|
||||
inline void pop();
|
||||
//! pushes an item initialized with its default constructor
|
||||
inline void push();
|
||||
//! pushes an item on the top of the stack
|
||||
void push(const TYPE& item);
|
||||
//! same as push() but returns the index the item was added at (or an error)
|
||||
inline ssize_t add();
|
||||
//! same as push() but returns the index the item was added at (or an error)
|
||||
ssize_t add(const TYPE& item);
|
||||
//! replace an item with a new one initialized with its default constructor
|
||||
inline ssize_t replaceAt(size_t index);
|
||||
//! replace an item with a new one
|
||||
ssize_t replaceAt(const TYPE& item, size_t index);
|
||||
|
||||
/*!
|
||||
* remove items
|
||||
*/
|
||||
|
||||
//! remove several items
|
||||
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
|
||||
//! remove one item
|
||||
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
|
||||
|
||||
/*!
|
||||
* sort (stable) the array
|
||||
*/
|
||||
|
||||
typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs);
|
||||
typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state);
|
||||
|
||||
inline status_t sort(compar_t cmp);
|
||||
inline status_t sort(compar_r_t cmp, void* state);
|
||||
|
||||
// for debugging only
|
||||
inline size_t getItemSize() const { return itemSize(); }
|
||||
|
||||
|
||||
/*
|
||||
* these inlines add some level of compatibility with STL. eventually
|
||||
* we should probably turn things around.
|
||||
*/
|
||||
typedef TYPE* iterator;
|
||||
typedef TYPE const* const_iterator;
|
||||
|
||||
inline iterator begin() { return editArray(); }
|
||||
inline iterator end() { return editArray() + size(); }
|
||||
inline const_iterator begin() const { return array(); }
|
||||
inline const_iterator end() const { return array() + size(); }
|
||||
inline void reserve(size_t n) { setCapacity(n); }
|
||||
inline bool empty() const{ return isEmpty(); }
|
||||
inline void push_back(const TYPE& item) { insertAt(item, size(), 1); }
|
||||
inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
|
||||
inline iterator erase(iterator pos) {
|
||||
ssize_t index = removeItemsAt(pos-array());
|
||||
return begin() + index;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void do_construct(void* storage, size_t num) const;
|
||||
virtual void do_destroy(void* storage, size_t num) const;
|
||||
virtual void do_copy(void* dest, const void* from, size_t num) const;
|
||||
virtual void do_splat(void* dest, const void* item, size_t num) const;
|
||||
virtual void do_move_forward(void* dest, const void* from, size_t num) const;
|
||||
virtual void do_move_backward(void* dest, const void* from, size_t num) const;
|
||||
};
|
||||
|
||||
// Vector<T> can be trivially moved using memcpy() because moving does not
|
||||
// require any change to the underlying SharedBuffer contents or reference count.
|
||||
template<typename T> struct trait_trivial_move<Vector<T> > { enum { value = true }; };
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No user serviceable parts from here...
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<class TYPE> inline
|
||||
Vector<TYPE>::Vector()
|
||||
: VectorImpl(sizeof(TYPE),
|
||||
((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
|
||||
|(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
|
||||
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0))
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
Vector<TYPE>::Vector(const Vector<TYPE>& rhs)
|
||||
: VectorImpl(rhs) {
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
|
||||
: VectorImpl(static_cast<const VectorImpl&>(rhs)) {
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
Vector<TYPE>::~Vector() {
|
||||
finish_vector();
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) {
|
||||
VectorImpl::operator = (rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
|
||||
VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
|
||||
VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
|
||||
VectorImpl::operator = (rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE* Vector<TYPE>::array() const {
|
||||
return static_cast<const TYPE *>(arrayImpl());
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
TYPE* Vector<TYPE>::editArray() {
|
||||
return static_cast<TYPE *>(editArrayImpl());
|
||||
}
|
||||
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE& Vector<TYPE>::operator[](size_t index) const {
|
||||
LOG_FATAL_IF(index>=size(),
|
||||
"%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
|
||||
int(index), int(size()));
|
||||
return *(array() + index);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE& Vector<TYPE>::itemAt(size_t index) const {
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE& Vector<TYPE>::top() const {
|
||||
return *(array() + size() - 1);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
TYPE& Vector<TYPE>::editItemAt(size_t index) {
|
||||
return *( static_cast<TYPE *>(editItemLocation(index)) );
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
TYPE& Vector<TYPE>::editTop() {
|
||||
return *( static_cast<TYPE *>(editItemLocation(size()-1)) );
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::insertVectorAt(const Vector<TYPE>& vector, size_t index) {
|
||||
return VectorImpl::insertVectorAt(reinterpret_cast<const VectorImpl&>(vector), index);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
|
||||
return VectorImpl::appendVector(reinterpret_cast<const VectorImpl&>(vector));
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t length) {
|
||||
return VectorImpl::insertArrayAt(array, index, length);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t length) {
|
||||
return VectorImpl::appendArray(array, length);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::insertAt(const TYPE& item, size_t index, size_t numItems) {
|
||||
return VectorImpl::insertAt(&item, index, numItems);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
void Vector<TYPE>::push(const TYPE& item) {
|
||||
return VectorImpl::push(&item);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::add(const TYPE& item) {
|
||||
return VectorImpl::add(&item);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::replaceAt(const TYPE& item, size_t index) {
|
||||
return VectorImpl::replaceAt(&item, index);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::insertAt(size_t index, size_t numItems) {
|
||||
return VectorImpl::insertAt(index, numItems);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
void Vector<TYPE>::pop() {
|
||||
VectorImpl::pop();
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
void Vector<TYPE>::push() {
|
||||
VectorImpl::push();
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::add() {
|
||||
return VectorImpl::add();
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::replaceAt(size_t index) {
|
||||
return VectorImpl::replaceAt(index);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t Vector<TYPE>::removeItemsAt(size_t index, size_t count) {
|
||||
return VectorImpl::removeItemsAt(index, count);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
|
||||
return VectorImpl::sort((VectorImpl::compar_t)cmp);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
|
||||
return VectorImpl::sort((VectorImpl::compar_r_t)cmp, state);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<class TYPE>
|
||||
void Vector<TYPE>::do_construct(void* storage, size_t num) const {
|
||||
construct_type( reinterpret_cast<TYPE*>(storage), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
|
||||
destroy_type( reinterpret_cast<TYPE*>(storage), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
|
||||
copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
|
||||
splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
|
||||
move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
|
||||
move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_VECTOR_H
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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_VECTOR_IMPL_H
|
||||
#define ANDROID_VECTOR_IMPL_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/Errors.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No user serviceable parts in here...
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
/*!
|
||||
* Implementation of the guts of the vector<> class
|
||||
* this ensures backward binary compatibility and
|
||||
* reduces code size.
|
||||
* For performance reasons, we expose mStorage and mCount
|
||||
* so these fields are set in stone.
|
||||
*
|
||||
*/
|
||||
|
||||
class VectorImpl
|
||||
{
|
||||
public:
|
||||
enum { // flags passed to the ctor
|
||||
HAS_TRIVIAL_CTOR = 0x00000001,
|
||||
HAS_TRIVIAL_DTOR = 0x00000002,
|
||||
HAS_TRIVIAL_COPY = 0x00000004,
|
||||
};
|
||||
|
||||
VectorImpl(size_t itemSize, uint32_t flags);
|
||||
VectorImpl(const VectorImpl& rhs);
|
||||
virtual ~VectorImpl();
|
||||
|
||||
/*! must be called from subclasses destructor */
|
||||
void finish_vector();
|
||||
|
||||
VectorImpl& operator = (const VectorImpl& rhs);
|
||||
|
||||
/*! C-style array access */
|
||||
inline const void* arrayImpl() const { return mStorage; }
|
||||
void* editArrayImpl();
|
||||
|
||||
/*! vector stats */
|
||||
inline size_t size() const { return mCount; }
|
||||
inline bool isEmpty() const { return mCount == 0; }
|
||||
size_t capacity() const;
|
||||
ssize_t setCapacity(size_t size);
|
||||
ssize_t resize(size_t size);
|
||||
|
||||
/*! append/insert another vector or array */
|
||||
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
|
||||
ssize_t appendVector(const VectorImpl& vector);
|
||||
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
|
||||
ssize_t appendArray(const void* array, size_t length);
|
||||
|
||||
/*! add/insert/replace items */
|
||||
ssize_t insertAt(size_t where, size_t numItems = 1);
|
||||
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
|
||||
void pop();
|
||||
void push();
|
||||
void push(const void* item);
|
||||
ssize_t add();
|
||||
ssize_t add(const void* item);
|
||||
ssize_t replaceAt(size_t index);
|
||||
ssize_t replaceAt(const void* item, size_t index);
|
||||
|
||||
/*! remove items */
|
||||
ssize_t removeItemsAt(size_t index, size_t count = 1);
|
||||
void clear();
|
||||
|
||||
const void* itemLocation(size_t index) const;
|
||||
void* editItemLocation(size_t index);
|
||||
|
||||
typedef int (*compar_t)(const void* lhs, const void* rhs);
|
||||
typedef int (*compar_r_t)(const void* lhs, const void* rhs, void* state);
|
||||
status_t sort(compar_t cmp);
|
||||
status_t sort(compar_r_t cmp, void* state);
|
||||
|
||||
protected:
|
||||
size_t itemSize() const;
|
||||
void release_storage();
|
||||
|
||||
virtual void do_construct(void* storage, size_t num) const = 0;
|
||||
virtual void do_destroy(void* storage, size_t num) const = 0;
|
||||
virtual void do_copy(void* dest, const void* from, size_t num) const = 0;
|
||||
virtual void do_splat(void* dest, const void* item, size_t num) const = 0;
|
||||
virtual void do_move_forward(void* dest, const void* from, size_t num) const = 0;
|
||||
virtual void do_move_backward(void* dest, const void* from, size_t num) const = 0;
|
||||
|
||||
private:
|
||||
void* _grow(size_t where, size_t amount);
|
||||
void _shrink(size_t where, size_t amount);
|
||||
|
||||
inline void _do_construct(void* storage, size_t num) const;
|
||||
inline void _do_destroy(void* storage, size_t num) const;
|
||||
inline void _do_copy(void* dest, const void* from, size_t num) const;
|
||||
inline void _do_splat(void* dest, const void* item, size_t num) const;
|
||||
inline void _do_move_forward(void* dest, const void* from, size_t num) const;
|
||||
inline void _do_move_backward(void* dest, const void* from, size_t num) const;
|
||||
|
||||
// These 2 fields are exposed in the inlines below,
|
||||
// so they're set in stone.
|
||||
void * mStorage; // base address of the vector
|
||||
size_t mCount; // number of items
|
||||
|
||||
const uint32_t mFlags;
|
||||
const size_t mItemSize;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SortedVectorImpl : public VectorImpl
|
||||
{
|
||||
public:
|
||||
SortedVectorImpl(size_t itemSize, uint32_t flags);
|
||||
SortedVectorImpl(const VectorImpl& rhs);
|
||||
virtual ~SortedVectorImpl();
|
||||
|
||||
SortedVectorImpl& operator = (const SortedVectorImpl& rhs);
|
||||
|
||||
//! finds the index of an item
|
||||
ssize_t indexOf(const void* item) const;
|
||||
|
||||
//! finds where this item should be inserted
|
||||
size_t orderOf(const void* item) const;
|
||||
|
||||
//! add an item in the right place (or replaces it if there is one)
|
||||
ssize_t add(const void* item);
|
||||
|
||||
//! merges a vector into this one
|
||||
ssize_t merge(const VectorImpl& vector);
|
||||
ssize_t merge(const SortedVectorImpl& vector);
|
||||
|
||||
//! removes an item
|
||||
ssize_t remove(const void* item);
|
||||
|
||||
protected:
|
||||
virtual int do_compare(const void* lhs, const void* rhs) const = 0;
|
||||
|
||||
private:
|
||||
ssize_t _indexOrderOf(const void* item, size_t* order = 0) const;
|
||||
|
||||
// these are made private, because they can't be used on a SortedVector
|
||||
// (they don't have an implementation either)
|
||||
ssize_t add();
|
||||
void pop();
|
||||
void push();
|
||||
void push(const void* item);
|
||||
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
|
||||
ssize_t appendVector(const VectorImpl& vector);
|
||||
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
|
||||
ssize_t appendArray(const void* array, size_t length);
|
||||
ssize_t insertAt(size_t where, size_t numItems = 1);
|
||||
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
|
||||
ssize_t replaceAt(size_t index);
|
||||
ssize_t replaceAt(const void* item, size_t index);
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_VECTOR_IMPL_H
|
||||
@@ -0,0 +1,41 @@
|
||||
/* utils/ashmem.h
|
||||
**
|
||||
** Copyright 2008 The Android Open Source Project
|
||||
**
|
||||
** This file is dual licensed. It may be redistributed and/or modified
|
||||
** under the terms of the Apache 2.0 License OR version 2 of the GNU
|
||||
** General Public License.
|
||||
*/
|
||||
|
||||
#ifndef _UTILS_ASHMEM_H
|
||||
#define _UTILS_ASHMEM_H
|
||||
|
||||
#include <linux/limits.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
#define ASHMEM_NAME_LEN 256
|
||||
|
||||
#define ASHMEM_NAME_DEF "dev/ashmem"
|
||||
|
||||
/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
|
||||
#define ASHMEM_NOT_REAPED 0
|
||||
#define ASHMEM_WAS_REAPED 1
|
||||
|
||||
/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
|
||||
#define ASHMEM_NOW_UNPINNED 0
|
||||
#define ASHMEM_NOW_PINNED 1
|
||||
|
||||
#define __ASHMEMIOC 0x77
|
||||
|
||||
#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
|
||||
#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
|
||||
#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t)
|
||||
#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4)
|
||||
#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long)
|
||||
#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6)
|
||||
#define ASHMEM_PIN _IO(__ASHMEMIOC, 7)
|
||||
#define ASHMEM_UNPIN _IO(__ASHMEMIOC, 8)
|
||||
#define ASHMEM_ISPINNED _IO(__ASHMEMIOC, 9)
|
||||
#define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10)
|
||||
|
||||
#endif /* _UTILS_ASHMEM_H */
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Handy utility functions and portability code.
|
||||
//
|
||||
#ifndef _LIBS_UTILS_MISC_H
|
||||
#define _LIBS_UTILS_MISC_H
|
||||
|
||||
#include <utils/Endian.h>
|
||||
|
||||
/* get #of elements in a static array */
|
||||
#ifndef NELEM
|
||||
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
|
||||
typedef void (*sysprop_change_callback)(void);
|
||||
void add_sysprop_change_callback(sysprop_change_callback cb, int priority);
|
||||
void report_sysprop_change();
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // _LIBS_UTILS_MISC_H
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 _LIBS_UTILS_THREADS_H
|
||||
#define _LIBS_UTILS_THREADS_H
|
||||
|
||||
/*
|
||||
* Please, DO NOT USE!
|
||||
*
|
||||
* This file is here only for legacy reasons. Instead, include directly
|
||||
* the headers you need below.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <utils/AndroidThreads.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <utils/Condition.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/RWLock.h>
|
||||
#include <utils/Thread.h>
|
||||
#endif
|
||||
|
||||
#endif // _LIBS_UTILS_THREADS_H
|
||||
Reference in New Issue
Block a user