diff options
Diffstat (limited to 'emulator/opengl/shared/emugl/common')
32 files changed, 0 insertions, 4197 deletions
diff --git a/emulator/opengl/shared/emugl/common/Android.mk b/emulator/opengl/shared/emugl/common/Android.mk deleted file mode 100644 index f481c0c89..000000000 --- a/emulator/opengl/shared/emugl/common/Android.mk +++ /dev/null @@ -1,71 +0,0 @@ -# This build script corresponds to a library containing many definitions -# common to both the guest and the host. They relate to -# -LOCAL_PATH := $(call my-dir) - -### emugl_common host library ########################################### - -commonSources := \ - id_to_object_map.cpp \ - lazy_instance.cpp \ - pod_vector.cpp \ - shared_library.cpp \ - smart_ptr.cpp \ - sockets.cpp \ - thread_store.cpp \ - -host_commonSources := $(commonSources) - -host_commonLdLibs := -lstdc++ - -ifneq (windows,$(HOST_OS)) - host_commonSources += thread_pthread.cpp - host_commonLdLibs += -ldl -lpthread -else - host_commonSources += thread_win32.cpp -endif - -$(call emugl-begin-host-static-library,libemugl_common) -LOCAL_SRC_FILES := $(host_commonSources) -$(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared) -$(call emugl-export,LDLIBS,$(host_commonLdLibs)) -$(call emugl-end-module) - -$(call emugl-begin-host64-static-library,lib64emugl_common) -LOCAL_SRC_FILES := $(host_commonSources) -$(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared) -$(call emugl-export,LDLIBS,$(host_commonLdLibs)) -$(call emugl-end-module) - - -### emugl_common_unittests ############################################## - -host_commonSources := \ - id_to_object_map_unittest.cpp \ - lazy_instance_unittest.cpp \ - pod_vector_unittest.cpp \ - mutex_unittest.cpp \ - shared_library_unittest.cpp \ - smart_ptr_unittest.cpp \ - thread_store_unittest.cpp \ - thread_unittest.cpp \ - unique_integer_map_unittest.cpp \ - -$(call emugl-begin-host-executable,emugl_common_host_unittests) -LOCAL_SRC_FILES := $(host_commonSources) -$(call emugl-import,libemugl_common libemugl_gtest) -$(call emugl-end-module) - -$(call emugl-begin-host64-executable,emugl64_common_host_unittests) -LOCAL_SRC_FILES := $(host_commonSources) -$(call emugl-import,lib64emugl_common lib64emugl_gtest) -$(call emugl-end-module) - - -$(call emugl-begin-host-shared-library,libemugl_test_shared_library) -LOCAL_SRC_FILES := testing/test_shared_library.cpp -$(call emugl-end-module) - -$(call emugl-begin-host64-shared-library,lib64emugl_test_shared_library) -LOCAL_SRC_FILES := testing/test_shared_library.cpp -$(call emugl-end-module) diff --git a/emulator/opengl/shared/emugl/common/id_to_object_map.cpp b/emulator/opengl/shared/emugl/common/id_to_object_map.cpp deleted file mode 100644 index 597c9eb1c..000000000 --- a/emulator/opengl/shared/emugl/common/id_to_object_map.cpp +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/id_to_object_map.h" - -#include <stdlib.h> - -namespace emugl { - -namespace { - -typedef IdToObjectMapBase::KeyType KeyType; - -enum { - kMinShift = 3, - kMaxShift = 31, - kMinCapacity = (1 << kMinShift), - kLoadScale = 1024, - kMinLoad = kLoadScale/4, // 25% minimum load. - kMaxLoad = kLoadScale*3/4, // 75% maximum load. - - kInvalidKey = IdToObjectMapBase::kMaxId + 1U, - kTombstone = IdToObjectMapBase::kMaxId + 2U, -}; - -// Return a number that indicates if the current |capacity| is appropriate -// to hold |size| items in our map. -// -1 -> the capacity is too small and needs to be increased. -// 0 -> the capacity is ok. -// +1 -> the capacity is too large and needs to be decreased. -int capacityCompare(size_t shift, size_t size) { - size_t capacity = 1U << shift; - // Essentially, one can rewrite: - // load < minLoad - // as: - // size / capacity < minLoad - // capacity * minLoad > size - if (capacity * kMinLoad > size * kLoadScale) - return +1; - - // Similarly, one can rewrite: - // load > maxLoad - // as: - // size / capacity > maxLoad - // capacity * maxLoad < size - if (capacity * kMaxLoad < size * kLoadScale) - return -1; - - return 0; -} - -size_t probeKeys(const KeyType* keys, size_t shift, KeyType key) { - static const int kPrimes[] = { - 1, /* For 1 << 0 */ - 2, - 3, - 7, - 13, - 31, - 61, - 127, - 251, - 509, - 1021, - 2039, - 4093, - 8191, - 16381, - 32749, - 65521, /* For 1 << 16 */ - 131071, - 262139, - 524287, - 1048573, - 2097143, - 4194301, - 8388593, - 16777213, - 33554393, - 67108859, - 134217689, - 268435399, - 536870909, - 1073741789, - 2147483647 /* For 1 << 31 */ - }; - - size_t slot = key % kPrimes[shift]; - size_t step = 0; - for (;;) { - KeyType k = keys[slot]; - if (k == kInvalidKey || k == kTombstone || k == key) - return slot; - - step += 1; - slot = (slot + step) & (1U << shift); - } -} - -} // namespace - -IdToObjectMapBase::IdToObjectMapBase() : - mCount(0), mShift(kMinShift) { - size_t capacity = 1U << mShift; - mKeys = static_cast<KeyType*>(::calloc(sizeof(mKeys[0]), capacity)); - mValues = static_cast<void**>(::calloc(sizeof(mValues[0]), capacity)); - for (size_t n = 0; n < capacity; ++n) { - mKeys[n] = kInvalidKey; - } -} - -IdToObjectMapBase::~IdToObjectMapBase() { - mShift = 0; - mCount = 0; - ::free(mKeys); - ::free(mValues); -} - -bool IdToObjectMapBase::contains(KeyType key) const { - size_t slot = probeKeys(mKeys, mShift, key); - switch (mKeys[slot]) { - case kInvalidKey: - case kTombstone: - return false; - default: - ; - } - return true; -} - -bool IdToObjectMapBase::find(KeyType key, void** value) const { - size_t slot = probeKeys(mKeys, mShift, key); - if (!isValidKey(mKeys[slot])) { - *value = NULL; - return false; - } - *value = mValues[slot]; - return true; -} - -void* IdToObjectMapBase::set(KeyType key, void* value) { - if (!value) - return remove(key); - - size_t slot = probeKeys(mKeys, mShift, key); - void* result; - if (isValidKey(mKeys[slot])) { - result = mValues[slot]; - mValues[slot] = value; - } else { - mKeys[slot] = key; - mValues[slot] = value; - result = NULL; - mCount++; - resize(mCount); - } - return result; -} - -void* IdToObjectMapBase::remove(KeyType key) { - size_t slot = probeKeys(mKeys, mShift, key); - if (!isValidKey(mKeys[slot])) - return NULL; - - void* result = mValues[slot]; - mValues[slot] = NULL; - mKeys[slot] = kTombstone; - mCount--; - return result; -} - -void IdToObjectMapBase::resize(size_t newSize) { - int ret = capacityCompare(mShift, newSize); - if (!ret) - return; - - size_t oldCapacity = 1U << mShift; - size_t newShift = mShift; - - if (ret < 0) { - // Capacity is too small and must be increased. - do { - if (newShift == kMaxShift) - break; - ++newShift; - } while (capacityCompare(newShift, newSize) < 0); - } else { - // Capacity is too large and must be decreased. - do { - if (newShift == kMinShift) - break; - newShift--; - } while (capacityCompare(newShift, newSize) > 0); - } - if (newShift == mShift) - return; - - // Allocate new arrays. - size_t newCapacity = 1U << newShift; - KeyType* newKeys = static_cast<KeyType*>( - ::calloc(sizeof(newKeys[0]), newCapacity)); - void** newValues = static_cast<void**>( - ::calloc(sizeof(newValues[0]), newCapacity)); - for (size_t n = 0; n < newCapacity; ++n) - newKeys[n] = kInvalidKey; - - // Copy old entries into new arrays. - for (size_t n = 0; n < oldCapacity; ++n) { - KeyType key = mKeys[n]; - if (isValidKey(key)) { - size_t newSlot = probeKeys(newKeys, newShift, key); - newKeys[newSlot] = key; - newValues[newSlot] = mValues[n]; - } - } - - // Swap arrays, and get rid of old ones. - ::free(mKeys); - ::free(mValues); - mKeys = newKeys; - mValues = newValues; - mShift = newShift; -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/id_to_object_map.h b/emulator/opengl/shared/emugl/common/id_to_object_map.h deleted file mode 100644 index e3d0a815e..000000000 --- a/emulator/opengl/shared/emugl/common/id_to_object_map.h +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (C) 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 EMUGL_COMMON_ID_TO_OBJECT_MAP_H -#define EMUGL_COMMON_ID_TO_OBJECT_MAP_H - -#include <stddef.h> - -namespace emugl { - -// Base implementation class for IdToObjectMap template. -// Used to reduce template-instanciated code generation. -class IdToObjectMapBase { -public: - // The type of keys in this map. - typedef unsigned KeyType; - - // Values higher than kMaxId cannot be used as map keys. - enum { - kMaxId = 0xfffffffdU, - }; - - static inline bool isValidKey(KeyType key) { - return key <= kMaxId; - } - -protected: - IdToObjectMapBase(); - - ~IdToObjectMapBase(); - - void clear(); - - // Return size - inline size_t size() const { return mCount; } - - inline size_t capacity() const { return 1U << mShift; } - - // Return true iff the map contains a given key. - bool contains(KeyType key) const; - - // Find a value associated with a given |key| in the map. - // On success, return true and sets |*value| to the value/pointer, - // which is _still_ owned by the map. - // On failure, return false and sets |*value| to NULL. - bool find(KeyType key, void** value) const; - - // Associate a value with a given |key| in the map. - // Return the old value for the key, if any. Caller is responsible - // for freeing it. - void* set(KeyType key, void* value); - - // Remove the value associated with a given |key|. - // Return the old value, if any. Caller is responsible for - // freeing it. - void* remove(KeyType key); - - size_t mCount; - size_t mShift; - KeyType* mKeys; - void** mValues; - -private: - // Resize the map if needed to ensure it can hold at least |newSize| - // entries. - void resize(size_t newSize); -}; - -// A templated data container that acts as a dictionary mapping unsigned -// integer keys to heap-allocated objects of type T. The dictionary -// owns the objects associated with its keys, and automatically destroys -// them when it is destroyed, or during replacement or removal. -template <class T> -class IdToObjectMap : public IdToObjectMapBase { -public: - // Initialize an empty instance. - IdToObjectMap() : IdToObjectMapBase() {} - - // Destroy this instance. - ~IdToObjectMap() { - clear(); - } - - // Return the number of items in this map. - inline size_t size() const { return IdToObjectMapBase::size(); } - - // Return true iff the map is empty. - inline bool empty() const { return !IdToObjectMapBase::size(); } - - // Remove all items from the map. - void clear(); - - // Returns true iff the dictionary contains a value for |key|. - inline bool contains(KeyType key) const { - return IdToObjectMapBase::contains(key); - } - - // Find the value corresponding to |key| in this map. - // On success, return true, and sets |*value| to point to the - // value (still owned by the instance). On failure, return false. - inline bool find(KeyType key, T** value) const { - return IdToObjectMapBase::find(key, reinterpret_cast<void**>(value)); - } - - // Return the value associated with a given |key|, or NULL if it is - // not in the map. Result is still owned by the map. - inline T* get(KeyType key) const { - T* result = NULL; - this->find(key, &result); - return result; - } - - // Associate |value| with a given |key|. Returns true if a previous - // value was replaced, and false if this is the first time a value - // was associated with the given key. IMPORTANT: This transfers - // ownership of |value| to the map instance. In case of replacement, - // the old value is automatically destroyed. Using NULL as the value - // is equivalent to calling remove(). - bool set(KeyType key, T* value); - - // Remove any value associated with |key|. - // Return true iff a value was associated with the key and destroyed - // by this function, false if there was no value associated with the - // key (or if it was NULL). - bool remove(KeyType key); -}; - -template <class T> -void IdToObjectMap<T>::clear() { - size_t n = capacity(); - while (n > 0) { - --n; - if (!isValidKey(mKeys[n])) - continue; - - delete static_cast<T*>(mValues[n]); - mValues[n] = NULL; - mKeys[n] = kMaxId + 1U; - } - mCount = 0; -} - -template <class T> -bool IdToObjectMap<T>::set(KeyType key, T* value) { - T* oldValue = static_cast<T*>(IdToObjectMapBase::set(key, value)); - if (!oldValue) { - return false; - } - delete oldValue; - return true; -} - -template <class T> -bool IdToObjectMap<T>::remove(KeyType key) { - T* oldValue = static_cast<T*>(IdToObjectMapBase::remove(key)); - if (!oldValue) - return false; - delete oldValue; - return true; -} - -} // namespace emugl - - -#endif // EMUGL_COMMON_ID_TO_OBJECT_MAP_H diff --git a/emulator/opengl/shared/emugl/common/id_to_object_map_unittest.cpp b/emulator/opengl/shared/emugl/common/id_to_object_map_unittest.cpp deleted file mode 100644 index 50740beb0..000000000 --- a/emulator/opengl/shared/emugl/common/id_to_object_map_unittest.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/id_to_object_map.h" - -#include <gtest/gtest.h> - -namespace emugl { - -namespace { - -typedef IdToObjectMapBase::KeyType KeyType; - -class Foo { -public: - Foo() : mVal(0) {} - Foo(int val) : mVal(val) {} - ~Foo() {} - int val() const { return mVal; } - void setVal(int val) { mVal = val; } -private: - int mVal; -}; - -} // namespace - -TEST(IdToObjectMap, Empty) { - IdToObjectMap<Foo> map; - EXPECT_TRUE(map.empty()); - EXPECT_EQ(0U, map.size()); -} - -TEST(IdToObjectMap, SetIntegerRange) { - IdToObjectMap<Foo> map; - KeyType kMax = 10000; - - // Add all items in the map. - for (KeyType n = 0; n < kMax; ++n) { - EXPECT_FALSE(map.set(n, new Foo(n))) << "For key " << n; - } - - // Check final size. - EXPECT_EQ(static_cast<size_t>(kMax), map.size()); - - // Find all items in the map. - for (KeyType n = 0; n < kMax; ++n) { - EXPECT_TRUE(map.contains(n)) << "For key " << n; - Foo* foo = NULL; - EXPECT_TRUE(map.find(n, &foo)) << "For key " << n; - if (foo) { - EXPECT_EQ(static_cast<int>(n), foo->val()) << "For key " << n; - } - } -} - -TEST(IdToObjectMap, RemoveAll) { - IdToObjectMap<Foo> map; - KeyType kMax = 10000; - - // Add all items in the map. - for (KeyType n = 0; n < kMax; ++n) { - EXPECT_FALSE(map.set(n, new Foo(n))) << "For key " << n; - } - - EXPECT_EQ(static_cast<size_t>(kMax), map.size()); - - for (KeyType n = 0; n < kMax; ++n) { - EXPECT_TRUE(map.remove(n)) << "For key " << n; - } - EXPECT_EQ(0U, map.size()); -} - -TEST(IdToObjectMap, RemoveOdd) { - IdToObjectMap<Foo> map; - KeyType kMax = 10000; - - // Add all items in the map. - for (KeyType n = 0; n < kMax; ++n) { - EXPECT_FALSE(map.set(n, new Foo(n))) << "For key " << n; - } - - EXPECT_EQ(static_cast<size_t>(kMax), map.size()); - - for (KeyType n = 0; n < kMax; ++n) { - if (n & 1) { - EXPECT_TRUE(map.remove(n)) << "For key " << n; - } - } - EXPECT_EQ(static_cast<size_t>(kMax / 2), map.size()); - - for (KeyType n = 0; n < kMax; ++n) { - if (n & 1) { - EXPECT_FALSE(map.contains(n)) << "For key " << n; - } else { - EXPECT_TRUE(map.contains(n)) << "For key " << n; - Foo* foo = NULL; - EXPECT_TRUE(map.find(n, &foo)) << "For key " << n; - if (foo) { - EXPECT_EQ(static_cast<int>(n), foo->val()); - } - } - } -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/lazy_instance.cpp b/emulator/opengl/shared/emugl/common/lazy_instance.cpp deleted file mode 100644 index ee715fa00..000000000 --- a/emulator/opengl/shared/emugl/common/lazy_instance.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/lazy_instance.h" - -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN 1 -# include <windows.h> -#else -# include <sched.h> -#endif - -namespace emugl { -namespace internal { - -typedef LazyInstanceState::AtomicType AtomicType; - -#if defined(__GNUC__) -static inline void compilerBarrier() { - __asm__ __volatile__ ("" : : : "memory"); -} -#else -#error "Your compiler is not supported" -#endif - -#if defined(__i386__) || defined(__x86_64__) -# define acquireBarrier() compilerBarrier() -# define releaseBarrier() compilerBarrier() -#else -# error "Your CPU is not supported" -#endif - -static inline AtomicType loadAcquire(AtomicType volatile* ptr) { - AtomicType ret = *ptr; - acquireBarrier(); - return ret; -} - -static inline void storeRelease(AtomicType volatile* ptr, AtomicType value) { - releaseBarrier(); - *ptr = value; -} - -static int atomicCompareAndSwap(AtomicType volatile* ptr, - int expected, - int value) { -#ifdef _WIN32 - return InterlockedCompareExchange(ptr, value, expected); -#elif defined(__GNUC__) - return __sync_val_compare_and_swap(ptr, expected, value); -#else -#error "Your compiler is not supported" -#endif -} - -static void yieldThread() { -#ifdef _WIN32 - ::Sleep(0); -#else - sched_yield(); -#endif -} - -bool LazyInstanceState::inInitState() { - return loadAcquire(&mState) == STATE_INIT; -} - -bool LazyInstanceState::needConstruction() { - AtomicType state = loadAcquire(&mState); - if (mState == STATE_DONE) - return false; - - state = atomicCompareAndSwap(&mState, STATE_INIT, STATE_CONSTRUCTING); - if (state == STATE_INIT) - return true; - - do { - yieldThread(); - state = loadAcquire(&mState); - } while (state != STATE_DONE); - - return false; -} - -void LazyInstanceState::doneConstructing() { - storeRelease(&mState, STATE_DONE); -} - -} // namespace internal -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/lazy_instance.h b/emulator/opengl/shared/emugl/common/lazy_instance.h deleted file mode 100644 index 6641c93d3..000000000 --- a/emulator/opengl/shared/emugl/common/lazy_instance.h +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (C) 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 EMUGL_COMMON_LAZY_INSTANCE_H -#define EMUGL_COMMON_LAZY_INSTANCE_H - -#include <new> - -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN 1 -# include <windows.h> -#endif - -namespace emugl { -namespace internal { - -// A LazyInstance is a helper template that can be used to perform -// thread-safe lazy initialization of static C++ objects without forcing -// the generation of C++ static constructors in the final executable. -// -// In a nutshell, you can replace a statement like: -// -// static Foo gFoo; -// -// With: -// -// static LazyInstance<Foo> gFoo = LAZY_INSTANCE_INIT; -// -// In the first case, a hidden static C++ constructor is embedded in the -// final executable, and executed at *load* *time* to call the Foo::Foo -// constructor on the gFoo object. -// -// On the second case, gFoo will only be initialized lazily, i.e. the first -// time any code actually tries to access the variable. -// -// Note that access is slightly different, i.e.: -// -// gFoo.get() returns a reference to the lazy-initialized object. -// gFoo.ptr() returns a pointer to it. -// gFoo->Something() is equivalent to doing gFoo.ptr()->Something(). -// -// 'gFoo' is stored in the .bss section and this doesn't use heap allocation. -// This class can only be used to perform lazy initialization through the -// class' default constructor. For more specialized cases, you will have -// to create a derived class, e.g.: -// -// class FoorWithDefaultParams : public Foo { -// public: -// FooWithDefaultParams() : Foo(<default-parameters>) {} -// }; -// -// LazyInstance<FooWithDefaultParams> gFoo = LAZY_INSTANCE_INIT; -// -// The implementation of LazyInstance relies on atomic operations and -// POD-struct class definitions, i.e. one that doesn't have any constructor, -// destructor, virtual members, or private ones, and that can be -// zero-initialized at link time. -// -// You can also use LazyInstance<> instances as static local variables, -// e.g.: -// -// Foo* getFooSingleton() { -// static LazyInstance<Foo> sFoo = LAZY_INSTANCE_INIT; -// return sFoo.ptr(); -// } -// -// This is useful on Windows which doesn't support thread-safe lazy -// initialization of static C++ local variables, or when the code is -// compiled with -fno-threadsafe-statics. -// -// This class is heavily inspired by Chromium's implementation of the -// same-named class (see $CHROMIUM/src/base/lazy_instance.h). - -// Atomic state variable type. Used to ensure to synchronize concurrent -// initialization and access without incurring the full cost of a mutex -// lock/unlock. -struct LazyInstanceState { - enum { - STATE_INIT = 0, - STATE_CONSTRUCTING = 1, - STATE_DONE = 2, - }; - - bool inInitState(); - bool needConstruction(); - void doneConstructing(); - -#ifdef _WIN32 - typedef LONG volatile AtomicType; -#else - typedef int volatile AtomicType; -#endif - - volatile AtomicType mState; -}; - -#define LAZY_INSTANCE_STATE_INIT \ - { ::emugl::internal::LazyInstanceState::STATE_INIT } - -} // namespace internal - -// LazyInstance template definition, see comment above for usage -// instructions. It is crucial to make this a POD-struct compatible -// type [1]. -// -// [1] http://en.wikipedia.org/wiki/Plain_Old_Data_Structures -// -template <class T> -struct LazyInstance { - bool hasInstance() const { return !mState.inInitState(); } - - T& get() const { return *ptr(); } - - T* ptr() const; - - const T* operator->() const { return ptr(); } - - T* operator->() { return ptr(); } - - T& operator*() { return get(); } - - // Really private, do not use. - union { - mutable internal::LazyInstanceState mState; - double mPadding; - }; - mutable char mStorage[sizeof(T)]; -}; - -// Initialization value, must resolve to all-0 to ensure the object -// instance is actually placed in the .bss -#define LAZY_INSTANCE_INIT { { LAZY_INSTANCE_STATE_INIT }, { 0 } } - -template <class T> -T* LazyInstance<T>::ptr() const { - if (mState.needConstruction()) { - new (mStorage) T(); - mState.doneConstructing(); - } - return reinterpret_cast<T*>(mStorage); -} - -} // namespace emugl - -#endif // EMUGL_COMMON_LAZY_INSTANCE_H diff --git a/emulator/opengl/shared/emugl/common/lazy_instance_unittest.cpp b/emulator/opengl/shared/emugl/common/lazy_instance_unittest.cpp deleted file mode 100644 index 824845f20..000000000 --- a/emulator/opengl/shared/emugl/common/lazy_instance_unittest.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/lazy_instance.h" - -#include "emugl/common/mutex.h" -#include "emugl/common/testing/test_thread.h" - -#include <gtest/gtest.h> - -namespace emugl { - -namespace { - -class Foo { -public: - Foo() : mValue(42) {} - int get() const { return mValue; } - void set(int value) { mValue = value; } - ~Foo() { mValue = 13; } -private: - int mValue; -}; - -class StaticCounter { -public: - StaticCounter() { - Mutex::AutoLock lock(mMutex); - mCounter++; - } - - int getValue() const { - Mutex::AutoLock lock(mMutex); - return mCounter; - } - -private: - static Mutex mMutex; - static int mCounter; -}; - -// NOTE: This introduces a static C++ constructor for this object file, -// but that's ok because a LazyInstance<Mutex> should not be used to -// test the behaviour of LazyInstance :-) -Mutex StaticCounter::mMutex; -int StaticCounter::mCounter = 0; - -} // namespace - -TEST(LazyInstance, HasInstance) { - LazyInstance<Foo> foo_instance = LAZY_INSTANCE_INIT; - EXPECT_FALSE(foo_instance.hasInstance()); - EXPECT_FALSE(foo_instance.hasInstance()); - foo_instance.ptr(); - EXPECT_TRUE(foo_instance.hasInstance()); -} - -TEST(LazyInstance, Simple) { - LazyInstance<Foo> foo_instance = LAZY_INSTANCE_INIT; - Foo* foo1 = foo_instance.ptr(); - EXPECT_TRUE(foo1); - EXPECT_EQ(42, foo_instance->get()); - foo1->set(10); - EXPECT_EQ(10, foo_instance->get()); - EXPECT_EQ(foo1, foo_instance.ptr()); -} - -// For the following test, launch 1000 threads that each try to get -// the instance pointer of a lazy instance. Then verify that they're all -// the same value. -// -// The lazy instance has a special constructor that will increment a -// global counter. This allows us to ensure that it is only called once. -// - -namespace { - -// The following is the shared structure between all threads. -struct MultiState { - MultiState(LazyInstance<StaticCounter>* staticCounter) : - mMutex(), mStaticCounter(staticCounter), mCount(0) {} - - enum { - kMaxThreads = 1000, - }; - - Mutex mMutex; - LazyInstance<StaticCounter>* mStaticCounter; - size_t mCount; - void* mValues[kMaxThreads]; - TestThread* mThreads[kMaxThreads]; -}; - -// The thread function for the test below. -static void* threadFunc(void* param) { - MultiState* state = static_cast<MultiState*>(param); - Mutex::AutoLock lock(state->mMutex); - if (state->mCount < MultiState::kMaxThreads) { - state->mValues[state->mCount++] = state->mStaticCounter->ptr(); - } - return NULL; -} - -} // namespace - -TEST(LazyInstance, MultipleThreads) { - LazyInstance<StaticCounter> counter_instance = LAZY_INSTANCE_INIT; - MultiState state(&counter_instance); - const size_t kNumThreads = MultiState::kMaxThreads; - - // Create all threads. - for (size_t n = 0; n < kNumThreads; ++n) { - state.mThreads[n] = new TestThread(threadFunc, &state); - } - - // Wait for their completion. - for (size_t n = 0; n < kNumThreads; ++n) { - state.mThreads[n]->join(); - } - - // Now check that the constructor was only called once. - EXPECT_EQ(1, counter_instance->getValue()); - - // Now compare all the store values, they should be the same. - StaticCounter* expectedValue = counter_instance.ptr(); - for (size_t n = 0; n < kNumThreads; ++n) { - EXPECT_EQ(expectedValue, state.mValues[n]) << "For thread " << n; - } - - for (size_t n = 0; n < kNumThreads; ++n) { - delete state.mThreads[n]; - } -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/mutex.h b/emulator/opengl/shared/emugl/common/mutex.h deleted file mode 100644 index c6cdcf2da..000000000 --- a/emulator/opengl/shared/emugl/common/mutex.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 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 EMUGL_MUTEX_H -#define EMUGL_MUTEX_H - -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN 1 -# include <windows.h> -#else -# include <pthread.h> -#endif - -namespace emugl { - -// Simple wrapper class for mutexes. -class Mutex { -public: - // Constructor. - Mutex() { -#ifdef _WIN32 - ::InitializeCriticalSection(&mLock); -#else - ::pthread_mutex_init(&mLock, NULL); -#endif - } - - // Destructor. - ~Mutex() { -#ifdef _WIN32 - ::DeleteCriticalSection(&mLock); -#else - ::pthread_mutex_destroy(&mLock); -#endif - } - - // Acquire the mutex. - void lock() { -#ifdef _WIN32 - ::EnterCriticalSection(&mLock); -#else - ::pthread_mutex_lock(&mLock); -#endif - } - - // Release the mutex. - void unlock() { -#ifdef _WIN32 - ::LeaveCriticalSection(&mLock); -#else - ::pthread_mutex_unlock(&mLock); -#endif - } - - // Helper class to lock / unlock a mutex automatically on scope - // entry and exit. - class AutoLock { - public: - AutoLock(Mutex& mutex) : mMutex(&mutex) { - mMutex->lock(); - } - - ~AutoLock() { - mMutex->unlock(); - } - private: - Mutex* mMutex; - }; - -private: -#ifdef _WIN32 - CRITICAL_SECTION mLock; -#else - pthread_mutex_t mLock; -#endif - -}; - -} // namespace emugl - -#endif // EMUGL_MUTEX_H diff --git a/emulator/opengl/shared/emugl/common/mutex_unittest.cpp b/emulator/opengl/shared/emugl/common/mutex_unittest.cpp deleted file mode 100644 index e952d75d4..000000000 --- a/emulator/opengl/shared/emugl/common/mutex_unittest.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/mutex.h" - -#include "emugl/common/testing/test_thread.h" - -#include <gtest/gtest.h> - -namespace emugl { - -// Check that construction and destruction doesn't crash. -TEST(Mutex, ConstructionDestruction) { - Mutex lock; -} - -// Check that a simple lock + unlock works. -TEST(Mutex, LockUnlock) { - Mutex lock; - lock.lock(); - lock.unlock(); -} - -// Check that AutoLock compiles and doesn't crash. -TEST(Mutex, AutoLock) { - Mutex mutex; - Mutex::AutoLock lock(mutex); -} - -// Wrapper class for threads. Does not use emugl::Thread intentionally. -// Common data type used by the following tests below. -struct ThreadParams { - ThreadParams() : mutex(), counter(0) {} - - Mutex mutex; - int counter; -}; - -// This thread function uses Mutex::lock/unlock to synchronize a counter -// increment operation. -static void* threadFunction(void* param) { - ThreadParams* p = static_cast<ThreadParams*>(param); - - p->mutex.lock(); - p->counter++; - p->mutex.unlock(); - return NULL; -} - -TEST(Mutex, Synchronization) { - const size_t kNumThreads = 2000; - TestThread* threads[kNumThreads]; - ThreadParams p; - - // Create and launch all threads. - for (size_t n = 0; n < kNumThreads; ++n) { - threads[n] = new TestThread(threadFunction, &p); - } - - // Wait until their completion. - for (size_t n = 0; n < kNumThreads; ++n) { - threads[n]->join(); - delete threads[n]; - } - - EXPECT_EQ(static_cast<int>(kNumThreads), p.counter); -} - -// This thread function uses a Mutex::AutoLock to protect the counter. -static void* threadAutoLockFunction(void* param) { - ThreadParams* p = static_cast<ThreadParams*>(param); - - Mutex::AutoLock lock(p->mutex); - p->counter++; - return NULL; -} - -TEST(Mutex, AutoLockSynchronization) { - const size_t kNumThreads = 2000; - TestThread* threads[kNumThreads]; - ThreadParams p; - - // Create and launch all threads. - for (size_t n = 0; n < kNumThreads; ++n) { - threads[n] = new TestThread(threadAutoLockFunction, &p); - } - - // Wait until their completion. - for (size_t n = 0; n < kNumThreads; ++n) { - threads[n]->join(); - delete threads[n]; - } - - EXPECT_EQ(static_cast<int>(kNumThreads), p.counter); -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/pod_vector.cpp b/emulator/opengl/shared/emugl/common/pod_vector.cpp deleted file mode 100644 index c8ec3a69b..000000000 --- a/emulator/opengl/shared/emugl/common/pod_vector.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/pod_vector.h" - -#include <stdlib.h> -#include <string.h> - -#define USE_MALLOC_USABLE_SIZE 0 - -namespace emugl { - -static inline void swapPointers(char** p1, char** p2) { - char* tmp = *p1; - *p1 = *p2; - *p2 = tmp; -} - -PodVectorBase::PodVectorBase(const PodVectorBase& other) { - initFrom(other.begin(), other.byteSize()); -} - -PodVectorBase& PodVectorBase::operator=(const PodVectorBase& other) { - initFrom(other.begin(), other.byteSize()); - return *this; -} - -PodVectorBase::~PodVectorBase() { - if (mBegin) { - // Sanity. - ::memset(mBegin, 0xee, byteSize()); - ::free(mBegin); - mBegin = NULL; - mEnd = NULL; - mLimit = NULL; - } -} - -void PodVectorBase::initFrom(const void* from, size_t fromLen) { - if (!fromLen || !from) { - mBegin = NULL; - mEnd = NULL; - mLimit = NULL; - } else { - mBegin = static_cast<char*>(::malloc(fromLen)); - mEnd = mLimit = mBegin + fromLen; - ::memcpy(mBegin, from, fromLen); - } -} - -void PodVectorBase::assignFrom(const PodVectorBase& other) { - resize(other.byteSize(), 1U); - ::memmove(begin(), other.begin(), byteSize()); -} - -void PodVectorBase::resize(size_t newSize, size_t itemSize) { - const size_t kMaxSize = maxItemCapacity(itemSize); - size_t oldCapacity = itemCapacity(itemSize); - const size_t kMinCapacity = 256 / itemSize; - - if (newSize < oldCapacity) { - // Only shrink if the new size is really small. - if (newSize < oldCapacity / 2 && oldCapacity > kMinCapacity) { - reserve(newSize, itemSize); - } - } else if (newSize > oldCapacity) { - size_t newCapacity = oldCapacity; - while (newCapacity < newSize) { - size_t newCapacity2 = newCapacity + (newCapacity >> 2) + 8; - if (newCapacity2 < newCapacity || newCapacity > kMaxSize) { - newCapacity = kMaxSize; - } else { - newCapacity = newCapacity2; - } - } - reserve(newCapacity, itemSize); - } - mEnd = mBegin + newSize * itemSize; -} - -void PodVectorBase::reserve(size_t newSize, size_t itemSize) { - if (newSize == 0) { - ::free(mBegin); - mBegin = NULL; - mEnd = NULL; - mLimit = NULL; - return; - } - - size_t oldByteSize = byteSize(); - size_t newByteCapacity = newSize * itemSize; - char* newBegin = static_cast<char*>(::realloc(mBegin, newByteCapacity)); - mBegin = newBegin; - mEnd = newBegin + oldByteSize; -#if USE_MALLOC_USABLE_SIZE - size_t usableSize = malloc_usable_size(mBegin); - if (usableSize > newByteCapacity) { - newByteCapacity = usableSize - (usableSize % itemSize); - } -#endif - mLimit = newBegin + newByteCapacity; - // Sanity. - if (newByteCapacity > oldByteSize) { - ::memset(mBegin + oldByteSize, 0, newByteCapacity - oldByteSize); - } -} - -void PodVectorBase::removeAt(size_t itemPos, size_t itemSize) { - size_t count = itemCount(itemSize); - if (itemPos < count) { - size_t pos = itemPos * itemSize; - ::memmove(mBegin + pos, - mBegin + pos + itemSize, - byteSize() - pos - itemSize); - resize(count - 1U, itemSize); - } -} - -void* PodVectorBase::insertAt(size_t itemPos, size_t itemSize) { - size_t count = this->itemCount(itemSize); - resize(count + 1, itemSize); - size_t pos = itemPos * itemSize; - if (itemPos < count) { - ::memmove(mBegin + pos + itemSize, - mBegin + pos, - count * itemSize - pos); - // Sanity to avoid copying pointers and other bad stuff. - ::memset(mBegin + pos, 0, itemSize); - } - return mBegin + pos; -} - -void PodVectorBase::swapAll(PodVectorBase* other) { - swapPointers(&mBegin, &other->mBegin); - swapPointers(&mEnd, &other->mEnd); - swapPointers(&mLimit, &other->mLimit); -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/pod_vector.h b/emulator/opengl/shared/emugl/common/pod_vector.h deleted file mode 100644 index c4e184bdf..000000000 --- a/emulator/opengl/shared/emugl/common/pod_vector.h +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (C) 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 EMUGL_COMMON_POD_VECTOR_H -#define EMUGL_COMMON_POD_VECTOR_H - - -#include <stddef.h> - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif -#ifndef __STDC_FORMAT_MACROS -#define __STDC_FORMAT_MACROS 1 -#endif -#include <stdint.h> - -#ifndef SIZE_MAX -#error "You must define __STDC_LIMIT_MACROS before including <stddint.h>" -#endif - -namespace emugl { - -// A PodVector is a templated vector-like type that is used to store -// POD-struct compatible items only. This allows the implementation to -// use ::memmove() to move items, and also malloc_usable_size() to -// determine the best capacity. -// -// std::vector<> is capable of doing this in theory, using horrible -// templating tricks that make error messages very difficult to -// understand. -// -// Note that a PodVector can be used to store items that contain pointers, -// as long as these do not point to items in the same container. -// -// The PodVector provides methods that also follow the std::vector<> -// conventions, i.e. push_back() is an alias for append(). -// - -// NOTE: This is a re-implementation of -// external/qemu/android/base/containers/PodVector.h for emugl. - -// PodVectorBase is a base, non-templated, implementation class that all -// PodVector instances derive from. This is used to reduce template -// specialization. Do not use directly, i..e it's an implementation detail. -class PodVectorBase { -protected: - PodVectorBase() : mBegin(NULL), mEnd(NULL), mLimit(NULL) {} - explicit PodVectorBase(const PodVectorBase& other); - PodVectorBase& operator=(const PodVectorBase& other); - ~PodVectorBase(); - - bool empty() const { return mEnd == mBegin; } - - size_t byteSize() const { return mEnd - mBegin; } - - size_t byteCapacity() const { return mLimit - mBegin; } - - void* begin() { return mBegin; } - const void* begin() const { return mBegin; } - void* end() { return mEnd; } - const void* end() const { return mEnd; } - - void* itemAt(size_t pos, size_t itemSize) { - return mBegin + pos * itemSize; - } - - const void* itemAt(size_t pos, size_t itemSize) const { - return mBegin + pos * itemSize; - } - - void assignFrom(const PodVectorBase& other); - - inline size_t itemCount(size_t itemSize) const { - return byteSize() / itemSize; - } - - inline size_t itemCapacity(size_t itemSize) const { - return byteCapacity() / itemSize; - } - - inline size_t maxItemCapacity(size_t itemSize) const { - return SIZE_MAX / itemSize; - } - - void resize(size_t newSize, size_t itemSize); - void reserve(size_t newSize, size_t itemSize); - - void removeAt(size_t index, size_t itemSize); - void* insertAt(size_t index, size_t itemSize); - void swapAll(PodVectorBase* other); - - char* mBegin; - char* mEnd; - char* mLimit; - -private: - void initFrom(const void* from, size_t fromLen); -}; - - -// A PodVector<T> holds a vector (dynamically resizable array) or items -// that must be POD-struct compatible (i.e. they cannot have constructors, -// destructors, or virtual members). This allows the implementation to be -// small, fast and efficient, memory-wise. -// -// If you want to implement a vector of C++ objects, consider using -// std::vector<> instead, but keep in mind that this implies a non-trivial -// cost when appending, inserting, removing items in the collection. -// -template <typename T> -class PodVector : public PodVectorBase { -public: - // Default constructor for an empty PodVector<T> - PodVector() : PodVectorBase() {} - - // Copy constructor. This copies all items from |other| into - // the new instance with ::memmove(). - PodVector(const PodVector& other) : PodVectorBase(other) {} - - // Assignment operator. - PodVector& operator=(const PodVector& other) { - this->assignFrom(other); - return *this; - } - - // Destructor, this simply releases the internal storage block that - // holds all the items, but doesn't touch them otherwise. - ~PodVector() {} - - // Return true iff the PodVector<T> instance is empty, i.e. does not - // have any items. - bool empty() const { return PodVectorBase::empty(); } - - // Return the number of items in the current PodVector<T> instance. - size_t size() const { return PodVectorBase::itemCount(sizeof(T)); } - - // Return the current capacity in the current PodVector<T> instance. - // Do not use directly, except if you know what you're doing. Try to - // use resize() or reserve() instead. - size_t capacity() const { - return PodVectorBase::itemCapacity(sizeof(T)); - } - - // Return the maximum capacity of any PodVector<T> instance. - static inline size_t maxCapacity() { return SIZE_MAX / sizeof(T); } - - // Resize the vector to ensure it can hold |newSize| - // items. This may or may not call reserve() under the hood. - // It's a fatal error to try to resize above maxCapacity(). - void resize(size_t newSize) { - PodVectorBase::resize(newSize, sizeof(T)); - } - - // Resize the vector's storage array to ensure that it can hold at - // least |newSize| items. It's a fatal error to try to resize above - // maxCapacity(). - void reserve(size_t newSize) { - PodVectorBase::reserve(newSize, sizeof(T)); - } - - // Return a pointer to the first item in the vector. This is only - // valid until the next call to any function that changes the size - // or capacity of the vector. Can be NULL if the vector is empty. - T* begin() { - return reinterpret_cast<T*>(PodVectorBase::begin()); - } - - // Return a constant pointer to the first item in the vector. This is - // only valid until the next call to any function that changes the - // size of capacity of the vector. - const T* begin() const { - return reinterpret_cast<T*>(PodVectorBase::begin()); - } - - // Return a pointer past the last item in the vector. I.e. if the - // result is not NULL, then |result - 1| points to the last item. - // Can be NULL if the vector is empty. - T* end() { - return reinterpret_cast<T*>(PodVectorBase::end()); - } - - // Return a constant pointer past the last item in the vector. I.e. if - // the result is not NULL, then |result - 1| points to the last item. - // Can be NULL if the vector is empty. - const T* end() const { - return reinterpret_cast<T*>(PodVectorBase::end()); - } - - // Returns a reference to the item a position |index| in the vector. - // It may be a fatal error to access an out-of-bounds position. - T& operator[](size_t index) { - return *reinterpret_cast<T*>( - PodVectorBase::itemAt(index, sizeof(T))); - } - - const T& operator[](size_t index) const { - return *reinterpret_cast<const T*>( - PodVectorBase::itemAt(index, sizeof(T))); - } - - // Increase the vector's size by 1, then move all items past a given - // position to the right. Return the position of the insertion point - // to let the caller copy the content it desires there. It's preferrable - // to use insert() directly, which will do the item copy for you. - T* emplace(size_t index) { - return reinterpret_cast<T*>( - PodVectorBase::insertAt(index, sizeof(T))); - } - - // Insert an item at a given position. |index| is the insertion position - // which must be between 0 and size() included, or a fatal error may - // occur. |item| is a reference to an item to copy into the array, - // byte-by-byte. - void insert(size_t index, const T& item) { - *(this->emplace(index)) = item; - } - - // Prepend an item at the start of a vector. This moves all vector items - // to the right, and is thus costly. |item| is a reference to an item - // to copy to the start of the vector. - void prepend(const T& item) { - *(this->emplace(0U)) = item; - } - - // Append an item at the end of a vector. Specialized version of insert() - // which always uses size() as the insertion position. - void append(const T& item) { - *(this->emplace(this->size())) = item; - } - - // Remove the item at a given position. |index| is the position of the - // item to delete. It must be between 0 and size(), included, or - // a fatal error may occur. Deleting the item at position size() - // doesn't do anything. - void remove(size_t index) { - PodVectorBase::removeAt(index, sizeof(T)); - } - - void swap(PodVector* other) { - PodVectorBase::swapAll(other); - } - - // Compatibility methods for std::vector<> - void push_back(const T& item) { append(item); } - void pop() { remove(0U); } - - typedef T* iterator; - typedef const T* const_iterator; -}; - -} // namespace emugl - -#endif // EMUGL_COMMON_POD_VECTOR_H diff --git a/emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp b/emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp deleted file mode 100644 index 9ce509ad6..000000000 --- a/emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/pod_vector.h" - -#include <gtest/gtest.h> - -namespace emugl { - -static int hashIndex(size_t n) { - return static_cast<int>(((n >> 14) * 13773) + (n * 51)); -} - -TEST(PodVector, Empty) { - PodVector<int> v; - EXPECT_TRUE(v.empty()); - EXPECT_EQ(0U, v.size()); -} - -TEST(PodVector, AppendOneItem) { - PodVector<int> v; - v.append(10234); - EXPECT_FALSE(v.empty()); - EXPECT_EQ(1U, v.size()); - EXPECT_EQ(10234, v[0]); -} - -TEST(PodVector, AppendLotsOfItems) { - PodVector<int> v; - const size_t kMaxCount = 10000; - for (size_t n = 0; n < kMaxCount; ++n) { - v.append(hashIndex(n)); - } - EXPECT_EQ(kMaxCount, v.size()); - for (size_t n = 0; n < kMaxCount; ++n) { - EXPECT_EQ(hashIndex(n), v[n]) << "At index " << n; - } -} - -TEST(PodVector, RemoveFrontItems) { - PodVector<int> v; - const size_t kMaxCount = 100; - for (size_t n = 0; n < kMaxCount; ++n) { - v.append(hashIndex(n)); - } - EXPECT_EQ(kMaxCount, v.size()); - for (size_t n = 0; n < kMaxCount; ++n) { - EXPECT_EQ(hashIndex(n), v[0]) << "At index " << n; - v.remove(0U); - EXPECT_EQ(kMaxCount - n - 1U, v.size()) << "At index " << n; - } -} - -TEST(PodVector, PrependItems) { - PodVector<int> v; - const size_t kMaxCount = 100; - for (size_t n = 0; n < kMaxCount; ++n) { - v.prepend(hashIndex(n)); - } - EXPECT_EQ(kMaxCount, v.size()); - for (size_t n = 0; n < kMaxCount; ++n) { - EXPECT_EQ(hashIndex(kMaxCount - n - 1), v[n]) << "At index " << n; - } -} - -TEST(PodVector, ResizeExpands) { - PodVector<int> v; - const size_t kMaxCount = 100; - const size_t kMaxCount2 = 10000; - for (size_t n = 0; n < kMaxCount; ++n) { - v.append(hashIndex(n)); - } - EXPECT_EQ(kMaxCount, v.size()); - v.resize(kMaxCount2); - EXPECT_EQ(kMaxCount2, v.size()); - for (size_t n = 0; n < kMaxCount; ++n) { - EXPECT_EQ(hashIndex(n), v[n]) << "At index " << n; - } -} - -TEST(PodVector, ResizeTruncates) { - PodVector<int> v; - const size_t kMaxCount = 10000; - const size_t kMaxCount2 = 10; - for (size_t n = 0; n < kMaxCount; ++n) { - v.append(hashIndex(n)); - } - EXPECT_EQ(kMaxCount, v.size()); - v.resize(kMaxCount2); - EXPECT_EQ(kMaxCount2, v.size()); - for (size_t n = 0; n < kMaxCount2; ++n) { - EXPECT_EQ(hashIndex(n), v[n]) << "At index " << n; - } -} - - -TEST(PodVector, AssignmentOperator) { - PodVector<int> v1; - const size_t kMaxCount = 10000; - for (size_t n = 0; n < kMaxCount; ++n) { - v1.append(hashIndex(n)); - } - EXPECT_EQ(kMaxCount, v1.size()); - - PodVector<int> v2; - v2 = v1; - - v1.reserve(0); - - EXPECT_EQ(kMaxCount, v2.size()); - for (size_t n = 0; n < kMaxCount; ++n) { - EXPECT_EQ(hashIndex(n), v2[n]) << "At index " << n; - } -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/scoped_pointer_vector.h b/emulator/opengl/shared/emugl/common/scoped_pointer_vector.h deleted file mode 100644 index 3d263e9a6..000000000 --- a/emulator/opengl/shared/emugl/common/scoped_pointer_vector.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 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 EMUGL_COMMON_SCOPED_POINTER_VECTOR_H -#define EMUGL_COMMON_SCOPED_POINTER_VECTOR_H - -namespace emugl { - -template <class T> -class ScopedPointerVector { - ScopedPointerVector -}; - -} // namespace emugl - -#endif // EMUGL_COMMON_SCOPED_POINTER_VECTOR_H diff --git a/emulator/opengl/shared/emugl/common/shared_library.cpp b/emulator/opengl/shared/emugl/common/shared_library.cpp deleted file mode 100644 index e78e36b5b..000000000 --- a/emulator/opengl/shared/emugl/common/shared_library.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/shared_library.h" - -#include <stddef.h> -#include <string.h> -#include <stdio.h> - -#ifndef _WIN32 -#include <dlfcn.h> -#include <stdlib.h> -#endif - -namespace emugl { - -#ifdef _WIN32 - -// static -SharedLibrary* SharedLibrary::open(const char* libraryName) { - HMODULE lib = LoadLibrary(libraryName); - return lib ? new SharedLibrary(lib) : NULL; -} - -SharedLibrary::SharedLibrary(HandleType lib) : mLib(lib) {} - -SharedLibrary::~SharedLibrary() { - if (mLib) { - FreeLibrary(mLib); - } -} - -SharedLibrary::FunctionPtr SharedLibrary::findSymbol( - const char* symbolName) { - if (!mLib || !symbolName) { - return NULL; - } - return reinterpret_cast<FunctionPtr>( - GetProcAddress(mLib, symbolName)); -} - -#else // !_WIN32 - -// static -SharedLibrary* SharedLibrary::open(const char* libraryName) { - const char* libPath = libraryName; - char* path = NULL; - - const char* libBaseName = strrchr(libraryName, '/'); - if (!libBaseName) { - libBaseName = libraryName; - } - - if (!strchr(libBaseName, '.')) { - // There is no extension in this library name, so append one. -#ifdef __APPLE__ - static const char kDllExtension[] = ".dylib"; -#else - static const char kDllExtension[] = ".so"; -#endif - size_t pathLen = strlen(libraryName) + sizeof(kDllExtension); - path = static_cast<char*>(malloc(pathLen)); - snprintf(path, pathLen, "%s%s", libraryName, kDllExtension); - libPath = path; - } - -#ifdef __APPLE__ - // On OSX, some libraries don't include an extension (notably OpenGL) - // On OSX we try to open |libraryName| first. If that doesn't exist, - // we try |libraryName|.dylib - void* lib = dlopen(libraryName, RTLD_NOW); - if (lib == NULL) { - lib = dlopen(libPath, RTLD_NOW); - } -#else - void* lib = dlopen(libPath, RTLD_NOW); -#endif - - if (path) { - free(path); - } - - return lib ? new SharedLibrary(lib) : NULL; -} - -SharedLibrary::SharedLibrary(HandleType lib) : mLib(lib) {} - -SharedLibrary::~SharedLibrary() { - if (mLib) { - dlclose(mLib); - } -} - -SharedLibrary::FunctionPtr SharedLibrary::findSymbol( - const char* symbolName) { - if (!mLib || !symbolName) { - return NULL; - } - return reinterpret_cast<FunctionPtr>(dlsym(mLib, symbolName)); -} - -#endif // !_WIN32 - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/shared_library.h b/emulator/opengl/shared/emugl/common/shared_library.h deleted file mode 100644 index f1d82fcee..000000000 --- a/emulator/opengl/shared/emugl/common/shared_library.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 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 EMUGL_COMMON_SHARED_LIBRARY_H -#define EMUGL_COMMON_SHARED_LIBRARY_H - -#ifdef _WIN32 -#include <windows.h> -#endif - -namespace emugl { - -// A class used to open a platform-specific shared library, and probe -// it for symbols. Usage is the following: -// -// // Open the library. -// SharedLibrary* library = SharedLibrary::open("libFoo"); -// if (!library) { -// ... could not find / open library! -// } -// -// //Probe for function symbol. -// FunctionPtr my_func = library->findSymbol("my_func"); -// -// // Closes library/ -// delete library; -// -class SharedLibrary { -public: - // Open a given library. If |libraryName| has no extension, a - // platform-appropriate extension is added and that path is opened. - // If the |libraryName| has an extension, that form is opened. - // - // On OSX, some libraries don't include an extension (notably OpenGL) - // On OSX we try to open |libraryName| first. If that doesn't exist, - // we try |libraryName|.dylib - // - // On success, returns a new SharedLibrary instance that must be - // deleted by the caller. - static SharedLibrary* open(const char* libraryName); - - // Closes an existing SharedLibrary instance. - ~SharedLibrary(); - - // Generic function pointer type, for values returned by the - // findSymbol() method. - typedef void (*FunctionPtr)(void); - - // Probe a given SharedLibrary instance to find a symbol named - // |symbolName| in it. Return its address as a FunctionPtr, or - // NULL if the symbol is not found. - FunctionPtr findSymbol(const char* symbolName); - -private: -#ifdef _WIN32 - typedef HMODULE HandleType; -#else - typedef void* HandleType; -#endif - - // Constructor intentionally hidden. - SharedLibrary(HandleType); - - HandleType mLib; -}; - -// Macro to compose emugl shared library name under various OS and bitness -// eg. -// on x86_64, EMUGL_LIBNAME("foo") --> "lib64foo" - -#if defined(__x86_64__) -# define EMUGL_LIBNAME(name) "lib64" name -#elif defined(__i386__) -# define EMUGL_LIBNAME(name) "lib" name -#else -/* This header is included by target w/o using EMUGL_LIBNAME(). Don't #error, leave it undefined */ -#endif - -} // namespace emugl - -#endif // EMUGL_COMMON_SHARED_LIBRARY_H diff --git a/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp b/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp deleted file mode 100644 index cb74efaa3..000000000 --- a/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/shared_library.h" - -#include <gtest/gtest.h> - -#include <string> - -#include <limits.h> -#include <string.h> - -// Hack to get the current executable's full path. -namespace testing { -namespace internal { - -extern std::string g_executable_path; - -} // namespace internal -} // namespace testing - -namespace emugl { - -namespace { - -// Return the name/path of the test shared library to load. -// Note that this doesn't include a platform-specific extension. -// This assumes that the test shared library is under the lib/ sub-directory -// of the current executable's path! -std::string GetTestLibraryName() { - static const char kSubDir[] = "lib/"; -#ifdef __x86_64__ - static const char kLibraryPrefix[] = "lib64"; -#else - static const char kLibraryPrefix[] = "lib"; -#endif - static const char kTestLibrarySuffix[] = "emugl_test_shared_library"; - - const char* exec_path = testing::internal::g_executable_path.c_str(); - -#ifdef _WIN32 - const char* p = strrchr(exec_path, '/'); - const char* p2 = strrchr(exec_path, '\\'); - if (p2) { - if (!p || p2 > p) { - p = p2; - } - } -#else - const char* p = strrchr(exec_path, '/'); -#endif - - std::string path; - - if (!p) { - path = "./"; - } else { - path = std::string(exec_path, p - exec_path + 1U); - } - path += kSubDir; - path += kLibraryPrefix; - path += kTestLibrarySuffix; - printf("Library path: %s\n", path.c_str()); - return path; -} - -class SharedLibraryTest : public testing::Test { -public: - SharedLibraryTest() { - // Locate the shared library - mLibraryPath = GetTestLibraryName(); - } - - ~SharedLibraryTest() {} - - const char* library_path() const { return mLibraryPath.c_str(); } - -private: - std::string mLibraryPath; -}; - -class ScopedSharedLibrary { -public: - explicit ScopedSharedLibrary(SharedLibrary* lib) : mLib(lib) {} - ~ScopedSharedLibrary() { - delete mLib; - } - SharedLibrary* get() const { return mLib; } - - SharedLibrary* operator->() { return mLib; } - - void release() { - delete mLib; - mLib = NULL; - } - -private: - SharedLibrary* mLib; -}; - -} // namespace - -TEST_F(SharedLibraryTest, Open) { - ScopedSharedLibrary lib(SharedLibrary::open(library_path())); - EXPECT_TRUE(lib.get()); -} - -TEST_F(SharedLibraryTest, OpenLibraryWithExtension) { - std::string path = library_path(); - - // test extension append - ScopedSharedLibrary libNoExtension(SharedLibrary::open(path.c_str())); - EXPECT_TRUE(libNoExtension.get()); - libNoExtension.release(); - -#ifdef _WIN32 - path += ".dll"; -#elif defined(__APPLE__) - // try to open the library without an extension - - path += ".dylib"; -#else - path += ".so"; -#endif - - // test open with prepended extension - ScopedSharedLibrary lib(SharedLibrary::open(path.c_str())); - EXPECT_TRUE(lib.get()); -} - -#ifdef __APPLE__ -TEST_F(SharedLibraryTest, OpenLibraryWithoutExtension) { - const char* library = "/System/Library/Frameworks/OpenGL.framework/OpenGL"; - ScopedSharedLibrary lib(SharedLibrary::open(library)); - EXPECT_TRUE(lib.get()); -} -#endif - -TEST_F(SharedLibraryTest, FindSymbol) { - ScopedSharedLibrary lib(SharedLibrary::open(library_path())); - EXPECT_TRUE(lib.get()); - - if (lib.get()) { - typedef int (*FooFunction)(void); - - FooFunction foo_func = reinterpret_cast<FooFunction>( - lib->findSymbol("foo_function")); - EXPECT_TRUE(foo_func); - EXPECT_EQ(42, (*foo_func)()); - } -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/smart_ptr.cpp b/emulator/opengl/shared/emugl/common/smart_ptr.cpp deleted file mode 100644 index 703487d87..000000000 --- a/emulator/opengl/shared/emugl/common/smart_ptr.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/smart_ptr.h" - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#endif - -namespace emugl { - -// Thread-safe atomic reference-counting type. -class RefCount { -public: - RefCount() : mCount(1) {} - ~RefCount() {} - - // Technically not thread-safe, use only for testing. - int count() const { return (int)mCount; } - - void increment() { -#ifdef _WIN32 - InterlockedIncrement(&mCount); -#else - __sync_fetch_and_add(&mCount, 1); -#endif - } - - bool decrement() { -#ifdef _WIN32 - return InterlockedDecrement(&mCount) == 0; -#else - return __sync_add_and_fetch(&mCount, -1) == 0; -#endif - } - -private: -#ifdef _WIN32 - LONG mCount; -#else - int mCount; -#endif -}; - - -// SmartPtrBase implementation. - -SmartPtrBase::SmartPtrBase(void* ptr) : mPtr(ptr), mRefCount(NULL) { - if (mPtr) - mRefCount = new RefCount(); -} - - -SmartPtrBase::SmartPtrBase(const SmartPtrBase& other) - : mPtr(other.mPtr), mRefCount(other.mRefCount) { - if (mRefCount) - mRefCount->increment(); -} - - -int SmartPtrBase::getRefCount() const { - return mRefCount ? mRefCount->count() : 0; -} - - -void SmartPtrBase::addRef() { - if (mRefCount) - mRefCount->increment(); -} - - -void* SmartPtrBase::copyFrom(const SmartPtrBase& other) { - void* old_ptr = release(); - - mPtr = other.mPtr; - mRefCount = other.mRefCount; - if (mRefCount) - mRefCount->increment(); - - return old_ptr; -} - - -void* SmartPtrBase::release() { - void* old_ptr = mPtr; - RefCount* old_refcount = mRefCount; - - if (old_refcount) { - mPtr = NULL; - mRefCount = NULL; - - if (old_refcount->decrement()) { - delete old_refcount; - return old_ptr; - } - } - - return NULL; -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/smart_ptr.h b/emulator/opengl/shared/emugl/common/smart_ptr.h deleted file mode 100644 index 73efdd64a..000000000 --- a/emulator/opengl/shared/emugl/common/smart_ptr.h +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (C) 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 EMUGL_SMART_PTR_H -#define EMUGL_SMART_PTR_H - -#include <stddef.h> - -namespace emugl { - -// Hidden atomic ref-counting implementation. -class RefCount; - -// Base class for all templated SmartPtr<> instances. Reduces -// template expansion and code. Consider this to be an implementation -// detail of SmartPtr<>, so don't rely on anything here. -class SmartPtrBase { -public: - // Defrault constructor. - SmartPtrBase() : mPtr(NULL), mRefCount(NULL) {} - - // Normal constructor. This takes ownership of |ptr|, though only - // template instances are capable of destroying the object. - explicit SmartPtrBase(void* ptr); - - // Copy-constructor, this increments the reference count. - SmartPtrBase(const SmartPtrBase& other); - - // Assignment operator, also increments the reference count. - SmartPtrBase& operator=(const SmartPtrBase& other); - - // Nothing happens in this destructor, the real work must be performed - // in subclasses. - ~SmartPtrBase() {} - - - // Used to enable 'if (smart_ptr) { ... }' properly. - operator void*() const { - return mPtr; - } - - // Return internal reference count value, only use for unit testing. - int getRefCount() const; - -protected: - // Used internally to increment the reference count. - void addRef(); - - // Copy the |other| into this instance, returns the old pointer value - // if it needs to be destroyed by the caller, or NULL otherwise. - void* copyFrom(const SmartPtrBase& other); - - // Used internally to decrement the reference count, if it reaches 0, - // returns the pointer to be destroyed, NULL otherwise. - void* release(); - - void* mPtr; - RefCount* mRefCount; -}; - - -// The real template class to be used for smart pointers. -// Typical uses: -// -// SmartPtr<Foo> ptr(new Foo()); // takes ownership. -// SmartPtr<Foo> ptr2; // empty pointer. -// ptr2 = ptr; // copies pointer + increment reference count. -// Foo* obj = ptr.Ptr(); // access pointed object. -// ptr->DoStuff(); // operate directly on pointed object. -// (*ptr)->DoStuff(); // same here. -// -// On scope exit, the internal reference count is decremented and the -// object is deleted automatically when it reaches 0, indicating that -// there are no more owners. -// -// IMPORTANT: You need to be sure that only one 'chain' of smart pointers -// own a given object. I.e. the following is incorrect: -// -// Foo* foo = new Foo(); // create new instance. -// SmartPtr<Foo> ptr(foo); // |ptr| takes ownership of |foo|. -// SmartPtr<Foo> ptr2(foo); // |ptr2| takes also ownership of |foo|. -// -// The problem is that |ptr| and |ptr2| don't know anything about each -// other, and will not share the same reference count. Once a smart pointer -// owns an object, only use other smart pointers that are copy-constructed -// or assigned with the initial one to keep everything consistent. -template <class T> -class SmartPtr : public emugl::SmartPtrBase { -public: - // Default constructor. The instance holds a NULL pointer. - SmartPtr() : SmartPtrBase() {} - - // Regular constructor, takes ownership of |ptr|. - explicit SmartPtr(T* ptr) : SmartPtrBase(ptr) {} - - // Copy-constructor, |this| and |other| will share the same internal - // reference count, which is incremented by 1. - SmartPtr(const SmartPtr& other) - : SmartPtrBase(reinterpret_cast<const SmartPtrBase&>(other)) {} - - // Assignment operator, same semantics as copy-constructor. - SmartPtr& operator=(const SmartPtr& other) { - void* old_ptr = copyFrom(static_cast<const SmartPtrBase&>(other)); - if (old_ptr) - delete reinterpret_cast<T*>(old_ptr); - return *this; - } - - // Destructor, decrements reference count and destroys the object - // if it reaches 0 (indicating this was the last owning smart pointer). - ~SmartPtr() { - void* ptr = release(); - if (ptr) - delete reinterpret_cast<T*>(ptr); - } - - // Return owned object instance, or NULL. - T* Ptr() const { - return reinterpret_cast<T*>(mPtr); - } - - // Return owned object instance, or NULL - const T* constPtr() const { - return reinterpret_cast<const T*>(mPtr); - } - - // Operate directly on owned object. - T* operator->() const { - return Ptr(); - } - - // Return reference to owned object. - T& operator*() const { - return *Ptr(); - } -}; - -} // namespace emugl - -#endif // EMUGL_SMART_PTR_H diff --git a/emulator/opengl/shared/emugl/common/smart_ptr_unittest.cpp b/emulator/opengl/shared/emugl/common/smart_ptr_unittest.cpp deleted file mode 100644 index db9e5f2a0..000000000 --- a/emulator/opengl/shared/emugl/common/smart_ptr_unittest.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/smart_ptr.h" - -#include <gtest/gtest.h> - -namespace emugl { - -// This Test sub-class is used to track allocations and deallocations of -// the MyTestClass instances that are created through newInstance(). -// See below for typical usage. -class SmartPtrTest : public testing::Test { -public: - SmartPtrTest() : mNewCount(0), mDeleteCount(0), mDoCount(0) {} - - ~SmartPtrTest() { - mNewCount = 0; - mDoCount = 0; - mDeleteCount = 0; - } - - class MyClass; - - MyClass* newInstance() { - return new MyClass(this); - } - - class MyClass { - public: - MyClass(SmartPtrTest* test) : mTest(test) { - mTest->mNewCount++; - } - - void doStuff() { - mTest->mDoCount++; - } - - ~MyClass() { - mTest->mDeleteCount++; - } - private: - SmartPtrTest* mTest; - }; - - int mNewCount; - int mDeleteCount; - int mDoCount; -}; - - -TEST_F(SmartPtrTest, Empty) { - SmartPtr<MyClass> ptr; - EXPECT_FALSE(ptr.Ptr()); - - EXPECT_EQ(0, mNewCount); - EXPECT_EQ(0, mDeleteCount); - EXPECT_EQ(0, mDoCount); -} - - -TEST_F(SmartPtrTest, SingleRef) { - MyClass* obj = newInstance(); - EXPECT_EQ(1, mNewCount); - - { - SmartPtr<MyClass> ptr(obj); - EXPECT_EQ(obj, ptr.Ptr()); - - EXPECT_EQ(1, mNewCount); - EXPECT_EQ(0, mDeleteCount); - EXPECT_EQ(0, mDoCount); - } - // Check that the object was deleted. - EXPECT_EQ(1, mDeleteCount); -} - - -TEST_F(SmartPtrTest, CopyConstructor) { - MyClass* obj = newInstance(); - EXPECT_EQ(1, mNewCount); - - { - SmartPtr<MyClass> ptr1(obj); - { - SmartPtr<MyClass> ptr2(ptr1); - EXPECT_EQ(2, ptr1.getRefCount()); - EXPECT_EQ(2, ptr2.getRefCount()); - EXPECT_EQ(1, mNewCount); - EXPECT_EQ(0, mDeleteCount); - EXPECT_EQ(0, mDoCount); - } - EXPECT_EQ(1, mNewCount); - EXPECT_EQ(0, mDeleteCount); - EXPECT_EQ(0, mDoCount); - } - EXPECT_EQ(1, mNewCount); - EXPECT_EQ(1, mDeleteCount); - EXPECT_EQ(0, mDoCount); -} - - -TEST_F(SmartPtrTest, AssignmentOperator) { - SmartPtr<MyClass> ptr1(newInstance()); - SmartPtr<MyClass> ptr2(newInstance()); - EXPECT_EQ(2, mNewCount); - EXPECT_EQ(0, mDeleteCount); - EXPECT_EQ(0, mDoCount); - - ptr2 = ptr1; - EXPECT_EQ(2, mNewCount); - EXPECT_EQ(1, mDeleteCount); - - EXPECT_EQ(ptr1.Ptr(), ptr2.Ptr()); - EXPECT_EQ(2, ptr1.getRefCount()); - EXPECT_EQ(2, ptr2.getRefCount()); -} - - -TEST_F(SmartPtrTest, ArrowOperator) { - SmartPtr<MyClass> ptr(newInstance()); - ptr->doStuff(); - EXPECT_EQ(1, mDoCount); - - (*ptr).doStuff(); - EXPECT_EQ(2, mDoCount); -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/sockets.cpp b/emulator/opengl/shared/emugl/common/sockets.cpp deleted file mode 100644 index 2a13d7293..000000000 --- a/emulator/opengl/shared/emugl/common/sockets.cpp +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/sockets.h" - -#include <errno.h> - -#ifdef _WIN32 -#include <winsock2.h> -#include <ws2tcpip.h> -#else -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <sys/un.h> -#include <sys/stat.h> -#endif - -#include <stddef.h> -#include <stdint.h> -#include <string.h> -#include <unistd.h> - -namespace emugl { - -namespace { - -static void socketSetReuseAddress(int s) { -#ifdef _WIN32 - // The default behaviour on Windows is equivalent to SO_REUSEADDR - // so we don't need to set this option. Moreover, one should never - // set this option with WinSock because it's badly implemented and - // generates a huge security issue. See: - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx -#else - int val = 1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); -#endif -} - -// Helper union to store a socket address. -struct SockAddr { - socklen_t len; - union { - sockaddr generic; - sockaddr_in inet; -#ifndef _WIN32 - sockaddr_un local; -#endif - }; - - int getFamily() const { return generic.sa_family; } - - void initEmpty() { - ::memset(this, 0, sizeof(*this)); - this->len = static_cast<socklen_t>(sizeof(*this)); - } - - int initFromInet(uint32_t ip_address, int port) { - if (port < 0 || port >= 65536) - return -EINVAL; - - ::memset(this, 0, sizeof(*this)); - this->inet.sin_family = AF_INET; - this->inet.sin_port = htons(port); - this->inet.sin_addr.s_addr = htonl(ip_address); - this->len = sizeof(this->inet); - return 0; - } - - int initFromLocalhost(int port) { - return initFromInet(0x7f000001, port); - } - -#ifndef _WIN32 - // Initialize the SockAddr from a Unix path. Returns 0 on success, - // or -errno code on failure. - int initFromUnixPath(const char* path) { - if (!path || !path[0]) - return -EINVAL; - - size_t pathLen = ::strlen(path); - if (pathLen >= sizeof(local.sun_path)) - return -E2BIG; - - ::memset(this, 0, sizeof(*this)); - this->local.sun_family = AF_LOCAL; - ::memcpy(this->local.sun_path, path, pathLen + 1U); - this->len = pathLen + offsetof(sockaddr_un, sun_path); - return 0; - } -#endif -}; - -int socketBindInternal(const SockAddr* addr, int socketType) { - int s = ::socket(addr->getFamily(), socketType, 0); - if (s < 0) - return -errno; - - // Bind to the socket. - if (::bind(s, &addr->generic, addr->len) < 0 || - ::listen(s, 5) < 0) { - int ret = -errno; - ::close(s); - return ret; - } - - socketSetReuseAddress(s); - return s; -} - -int socketConnectInternal(const SockAddr* addr, int socketType) { - int s = ::socket(addr->getFamily(), socketType, 0); - if (s < 0) - return -errno; - - int ret; - do { - ret = ::connect(s, &addr->generic, addr->len); - } while (ret < 0 && errno == EINTR); - - if (ret < 0) { - ret = -errno; - ::close(s); - return ret; - } - - return s; -} - -} // namespace - -void socketTcpDisableNagle(int s) { - // disable Nagle algorithm to improve bandwidth of small - // packets which are quite common in our implementation. -#ifdef _WIN32 - DWORD flag; -#else - int flag; -#endif - flag = 1; - setsockopt(s, IPPROTO_TCP, TCP_NODELAY, - (const char*)&flag, sizeof(flag)); -} - -int socketGetPort(int s) { - SockAddr addr; - addr.initEmpty(); - if (getsockname(s, &addr.generic, &addr.len) < 0) { - return -errno; - } - switch (addr.generic.sa_family) { - case AF_INET: - return ntohs(addr.inet.sin_port); - default: - ; - } - return -EINVAL; -} - -#ifndef _WIN32 -int socketLocalServer(const char* path, int socketType) { - SockAddr addr; - int ret = addr.initFromUnixPath(path); - if (ret < 0) { - return ret; - } - return socketBindInternal(&addr, socketType); -} - -int socketLocalClient(const char* path, int socketType) { - SockAddr addr; - int ret = addr.initFromUnixPath(path); - if (ret < 0) { - return ret; - } - return socketConnectInternal(&addr, socketType); -} -#endif // !_WIN32 - -int socketTcpLoopbackServer(int port, int socketType) { - SockAddr addr; - int ret = addr.initFromLocalhost(port); - if (ret < 0) { - return ret; - } - return socketBindInternal(&addr, socketType); -} - -int socketTcpLoopbackClient(int port, int socketType) { - SockAddr addr; - int ret = addr.initFromLocalhost(port); - if (ret < 0) { - return ret; - } - return socketConnectInternal(&addr, socketType); -} - -int socketTcpClient(const char* hostname, int port, int socketType) { - // TODO(digit): Implement this. - return -ENOSYS; -} - -int socketAccept(int serverSocket) { - int ret; - do { - ret = ::accept(serverSocket, NULL, NULL); - } while (ret < 0 && errno == EINTR); - return ret; -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/sockets.h b/emulator/opengl/shared/emugl/common/sockets.h deleted file mode 100644 index 11e7ac7dd..000000000 --- a/emulator/opengl/shared/emugl/common/sockets.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 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 EMUGL_COMMON_SOCKETS_H -#define EMUGL_COMMON_SOCKETS_H - -// A set of helper functions used to deal with sockets in a portable way. - -namespace emugl { - -// Disable Nagle's algorithm for socket descriptor |s|. This assumes -// that |s| is a TCP socket descriptor. -void socketTcpDisableNagle(int s); - -// Return the port associated with a given IP or IPv6 socket, -// or -errno code on failure. -int socketGetPort(int s); - -// Bind to a local/Unix path, and return its socket descriptor on success, -// or -errno code on failure. -int socketLocalServer(const char* path, int socketType); - -// Connect to a Unix local path, and return a new socket descriptor -// on success, or -errno code on failure. -int socketLocalClient(const char* path, int socketType); - -// Bind to a localhost TCP socket, and return its socket descriptor on -// success, or -errno code on failure. -int socketTcpLoopbackServer(int port, int socketType); - -// Connect to a localhost TCP port, and return a new socket descriptor on -// success, or -errno code on failure. -int socketTcpLoopbackClient(int port, int socketType); - -// Connect to a TCP host, and return a new socket descriptor on -// success, or -errno code on failure. -int socketTcpClient(const char* hostname, int port, int socketType); - -// Accept a new connection. |serverSocket| must be a bound server socket -// descriptor. Returns new socket descriptor on success, or -errno code -// on failure. -int socketAccept(int serverSocket); - -} // namespace emugl - -#endif // EMUGL_COMMON_SOCKETS_H diff --git a/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp b/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp deleted file mode 100644 index 598a963a8..000000000 --- a/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 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. - -// This source file must be compiled into a simple shared library which -// will be used by shared_library_unittest.cpp to verify that the -// emugl::SharedLibrary class works properly. - - -extern "C" int foo_function(void) { - return 42; -} diff --git a/emulator/opengl/shared/emugl/common/testing/test_thread.h b/emulator/opengl/shared/emugl/common/testing/test_thread.h deleted file mode 100644 index 2d758b3f4..000000000 --- a/emulator/opengl/shared/emugl/common/testing/test_thread.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) 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 EMUGL_COMMON_TESTING_TEST_THREAD_H -#define EMUGL_COMMON_TESTING_TEST_THREAD_H - -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN 1 -# include <windows.h> -#else -# include <pthread.h> -#endif - -namespace emugl { - -// Very basic platform thread wrapper that only uses a tiny stack. -// This shall only be used during unit testing, and allows test code -// to not depend on the implementation of emugl::Thread. -class TestThread { -public: - // Main thread function type. - typedef void* (ThreadFunction)(void* param); - - // Constructor actually launches a new platform thread. - TestThread(ThreadFunction* func, void* funcParam) { -#ifdef _WIN32 - mThread = CreateThread(NULL, - 16384, - (DWORD WINAPI (*)(void*))func, - funcParam, - NULL, - NULL); -#else - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, 16384); - pthread_create(&mThread, &attr, func, funcParam); - pthread_attr_destroy(&attr); -#endif - } - - ~TestThread() { -#ifdef _WIN32 - CloseHandle(mThread); -#endif - } - - void join() { -#ifdef _WIN32 - WaitForSingleObject(mThread, INFINITE); -#else - void* ret = NULL; - pthread_join(mThread, &ret); -#endif - } - -private: -#ifdef _WIN32 - HANDLE mThread; -#else - pthread_t mThread; -#endif -}; - -} // namespace emugl - -#endif // EMUGL_COMMON_TESTING_TEST_THREAD_H diff --git a/emulator/opengl/shared/emugl/common/thread.h b/emulator/opengl/shared/emugl/common/thread.h deleted file mode 100644 index d0f7d206d..000000000 --- a/emulator/opengl/shared/emugl/common/thread.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (C) 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 EMUGL_COMMON_THREAD_H -#define EMUGL_COMMON_THREAD_H - -#ifdef _WIN32 -#include <windows.h> -#else -#include <pthread.h> -#endif - -#include <stdint.h> - -namespace emugl { - -// Wrapper class for platform-specific threads. -// To create your own thread, define a sub-class of emugl::Thread -// and override its main() method. -// -// For example: -// -// class MyThread : public emugl::Thread { -// public: -// MyThread() : Thread() {} -// -// virtual intptr_t main() { -// ... main thread loop implementation -// return 0; -// } -// }; -// -// ... -// -// // Create new instance, but does not start it. -// MyThread* thread = new MyThread(); -// -// // Start the thread. -// thread->start(); -// -// // Wait for thread completion, and gets result into |exitStatus|. -// int exitStatus; -// thread->wait(&exitStatus); -// -class Thread { -public: - // Public constructor. - Thread(); - - // Virtual destructor. - virtual ~Thread(); - - // Override this method in your own thread sub-classes. This will - // be called when start() is invoked on the Thread instance. - virtual intptr_t main() = 0; - - // Start a thread instance. Return true on success, false otherwise - // (e.g. if the thread was already started or terminated). - bool start(); - - // Wait for thread termination and retrieve exist status into - // |*exitStatus|. Return true on success, false otherwise. - // NOTE: |exitStatus| can be NULL. - bool wait(intptr_t *exitStatus); - - // Check whether a thread has terminated. On success, return true - // and sets |*exitStatus|. On failure, return false. - // NOTE: |exitStatus| can be NULL. - bool tryWait(intptr_t *exitStatus); - -private: -#ifdef _WIN32 - static DWORD WINAPI thread_main(void* arg); - - HANDLE mThread; - DWORD mThreadId; - CRITICAL_SECTION mLock; -#else // !WIN32 - static void* thread_main(void* arg); - - pthread_t mThread; - pthread_mutex_t mLock; -#endif - intptr_t mExitStatus; - bool mIsRunning; -}; - -} // namespace emugl - -#endif // EMUGL_COMMON_THREAD_H - diff --git a/emulator/opengl/shared/emugl/common/thread_pthread.cpp b/emulator/opengl/shared/emugl/common/thread_pthread.cpp deleted file mode 100644 index 5dbc3abb8..000000000 --- a/emulator/opengl/shared/emugl/common/thread_pthread.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/thread.h" - -#include "emugl/common/thread_store.h" - -#include <stdio.h> - -namespace emugl { - -namespace { - -class ScopedLocker { -public: - ScopedLocker(pthread_mutex_t* mutex) : mMutex(mutex) { - pthread_mutex_lock(mMutex); - } - - ~ScopedLocker() { - pthread_mutex_unlock(mMutex); - } -private: - pthread_mutex_t* mMutex; -}; - -} // namespace - -Thread::Thread() : - mThread((pthread_t)NULL), - mExitStatus(0), - mIsRunning(false) { - pthread_mutex_init(&mLock, NULL); -} - -Thread::~Thread() { - pthread_mutex_destroy(&mLock); -} - -bool Thread::start() { - bool ret = true; - pthread_mutex_lock(&mLock); - mIsRunning = true; - if (pthread_create(&mThread, NULL, thread_main, this)) { - ret = false; - mIsRunning = false; - } - pthread_mutex_unlock(&mLock); - return ret; -} - -bool Thread::wait(intptr_t *exitStatus) { - { - ScopedLocker locker(&mLock); - if (!mIsRunning) { - // Thread already stopped. - if (exitStatus) { - *exitStatus = mExitStatus; - } - return true; - } - } - - // NOTE: Do not hold the lock when waiting for the thread to ensure - // it can update mIsRunning and mExitStatus properly in thread_main - // without blocking. - void *retval; - if (pthread_join(mThread, &retval)) { - return false; - } - if (exitStatus) { - *exitStatus = (intptr_t)retval; - } - return true; -} - -bool Thread::tryWait(intptr_t *exitStatus) { - ScopedLocker locker(&mLock); - if (!mIsRunning) { - return false; - } - if (exitStatus) { - *exitStatus = mExitStatus; - } - return true; -} - -// static -void* Thread::thread_main(void *arg) { - Thread* self = reinterpret_cast<Thread*>(arg); - intptr_t ret = self->main(); - - pthread_mutex_lock(&self->mLock); - self->mIsRunning = false; - self->mExitStatus = ret; - pthread_mutex_unlock(&self->mLock); - - ::emugl::ThreadStore::OnThreadExit(); - - return (void*)ret; -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/thread_store.cpp b/emulator/opengl/shared/emugl/common/thread_store.cpp deleted file mode 100644 index ea64c6f3f..000000000 --- a/emulator/opengl/shared/emugl/common/thread_store.cpp +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/thread_store.h" - -#ifdef _WIN32 -#include "emugl/common/lazy_instance.h" -#endif - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -// Set to 1 to print debug messages. -#define DEBUG_THREAD_STORE 0 - -#if DEBUG_THREAD_STORE -# define D(...) do { printf("%s:%d: ", __FUNCTION__, __LINE__); printf(__VA_ARGS__); fflush(stdout); } while (0) -#else -# define D(...) ((void)0) -#endif - -namespace emugl { - -#ifdef _WIN32 - -namespace { - -// The ThreadStore implementation on Windows is very tricky, because -// TlsAlloc() doesn't allow one to provide a destructor function. As -// such threads are expected to destroy all TLS values explicitely. -// -// To solve this issue, this source file provides a static method called -// ThreadStore::OnThreadExit() that must be called when a thread exits, -// which will cleanup all values for the current thread. -// -// But this forces us to track thread-specific values ourselves. - -// Maximum amount of thread-specific slots supported by this implementation. -enum { - kMaxTlsSlots = 64 -}; - -// TlsSlotArray is a thread-specific array of values. Instances will -// be stored in a Win32 TLS value controlled by a single master TLS -// key. -// -typedef void* TlsSlotArray[kMaxTlsSlots]; - -// Global state shared by all threads -class GlobalState { -public: - GlobalState() { - D("Entering\n"); - mMasterTls = TlsAlloc(); - D("Master TLS = %d\n", (int)mMasterTls); - InitializeCriticalSection(&mSection); - mLastIndex = 0; - ::memset(mDestructors, 0, sizeof(mDestructors)); - D("Exiting\n"); - } - - // Register a new TLS key, or return -1 on error (too many keys). - // |destroy| is the destructor function for the key. - int registerKey(ThreadStore::Destructor* destroy) { - D("Entering destroy=%p\n", destroy); - int ret = -1; - EnterCriticalSection(&mSection); - if (mLastIndex < kMaxTlsSlots) { - ret = mLastIndex++; - mDestructors[ret] = destroy; - } - LeaveCriticalSection(&mSection); - D("Exiting newKey=%d\n", ret); - return ret; - } - - void unregisterKey(int key) { - D("key=%d\n", key); - if (key < 0 || key >= kMaxTlsSlots) { - D("Invalid key\n"); - return; - } - - // Note: keys are not reusable, but remove the destructor to avoid - // crashes in leaveCurrentThread() when it points to a function that - // is going to be unloaded from the process' address space. - EnterCriticalSection(&mSection); - mDestructors[key] = NULL; - LeaveCriticalSection(&mSection); - D("Exiting\n"); - } - - // Get the current thread-local value for a given |key|. - void* getValue(int key) const { - D("Entering key=%d\n", key); - if (key < 0 || key >= kMaxTlsSlots) { - D("Invalid key, result=NULL\n"); - return NULL; - } - - TlsSlotArray* array = getArray(); - void* ret = (*array)[key]; - D("Exiting keyValue=%p\n", ret); - return ret; - } - - // Set the current thread-local |value| for a given |key|. - void setValue(int key, void* value) { - D("Entering key=%d\n",key); - if (key < 0 || key >= kMaxTlsSlots) { - D("Invalid key, returning\n"); - return; - } - - TlsSlotArray* array = getArray(); - (*array)[key] = value; - D("Exiting\n"); - } - - // Call this when a thread exits to destroy all its thread-local values. - void leaveCurrentThread() { - D("Entering\n"); - TlsSlotArray* array = - reinterpret_cast<TlsSlotArray*>(TlsGetValue(mMasterTls)); - if (!array) { - D("Exiting, no thread-local data in this thread\n"); - return; - } - - for (size_t n = 0; n < kMaxTlsSlots; ++n) { - void* value = array[n]; - if (value) { - (*array)[n] = NULL; - // NOTE: In theory, a destructor could reset the slot to - // a new value, and we would have to loop in this function - // in interesting ways. In practice, ignore the issue. - EnterCriticalSection(&mSection); - ThreadStore::Destructor* destroy = mDestructors[n]; - LeaveCriticalSection(&mSection); - if (destroy) { - D("Calling destructor %p for key=%d, with value=%p\n", - destroy, (int)n, value); - (*destroy)(value); - } - } - } - TlsSetValue(mMasterTls, NULL); - ::free(array); - D("Exiting\n"); - } - -private: - // Return the thread-local array of TLS slots for the current thread. - // Cannot return NULL. - TlsSlotArray* getArray() const { - D("Entering\n"); - TlsSlotArray* array = - reinterpret_cast<TlsSlotArray*>(TlsGetValue(mMasterTls)); - if (!array) { - array = reinterpret_cast<TlsSlotArray*>( - ::calloc(sizeof(*array), 1)); - TlsSetValue(mMasterTls, array); - D("Allocated new array at %p\n", array); - } else { - D("Retrieved array at %p\n", array); - } - return array; - } - - DWORD mMasterTls; - CRITICAL_SECTION mSection; - int mLastIndex; - ThreadStore::Destructor* mDestructors[kMaxTlsSlots]; -}; - -LazyInstance<GlobalState> gGlobalState = LAZY_INSTANCE_INIT; - -} // namespace - -ThreadStore::ThreadStore(Destructor* destroy) { - D("Entering this=%p destroy=%p\n", this, destroy); - mKey = gGlobalState->registerKey(destroy); - D("Exiting this=%p key=%d\n", this, mKey); -} - -ThreadStore::~ThreadStore() { - D("Entering this=%p\n", this); - GlobalState* state = gGlobalState.ptr(); - state->unregisterKey(mKey); - D("Exiting this=%p\n", this); -} - -void* ThreadStore::get() const { - D("Entering this=%p\n", this); - void* ret = gGlobalState->getValue(mKey); - D("Exiting this=%p value=%p\n", this, ret); - return ret; -} - -void ThreadStore::set(void* value) { - D("Entering this=%p value=%p\n", this, value); - gGlobalState->setValue(mKey, value); - D("Exiting this=%p\n", this); -} - -// static -void ThreadStore::OnThreadExit() { - gGlobalState->leaveCurrentThread(); -} - -#else // !_WIN32 - -ThreadStore::ThreadStore(Destructor* destroy) { - int ret = pthread_key_create(&mKey, destroy); - if (ret != 0) { - fprintf(stderr, - "Could not create thread store key: %s\n", - strerror(ret)); - exit(1); - } -} - -ThreadStore::~ThreadStore() { - pthread_key_delete(mKey); -} - -#endif // !_WIN32 - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/thread_store.h b/emulator/opengl/shared/emugl/common/thread_store.h deleted file mode 100644 index 5fd08bdeb..000000000 --- a/emulator/opengl/shared/emugl/common/thread_store.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (C) 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 EMUGL_COMMON_THREAD_STORE_H -#define EMUGL_COMMON_THREAD_STORE_H - -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN 1 -# include <windows.h> -#else -# include <pthread.h> -#endif - -namespace emugl { - -// A class to model storage of thread-specific values, that can be -// destroyed on thread exit. -// -// Note that on Windows, a thread must call OnThreadExit() explicitly -// here to ensure that the values are probably discarded. This is an -// unfortunate requirement of the Win32 API, which doesn't support -// destructors at all. -// -// There are various hacks on the web to try to achieve this automatically -// (e.g. [1]) but they rely on using the Microsoft build tools, -// which doesn't work for us. -// -// Note another important issue with ThreadStore instances: if you create -// one instance in a shared library, you need to make sure that it is -// always destroyed before the library is unloaded. Otherwise, future -// thread exit will likely crash, due to calling a destructor function -// that is no longer in the process' address space. -// -// Finally, destroying an instance does _not_ free the corresponding values, -// because doing so properly requires coordinating all participating threads, -// which is impossible to achieve in the most general case. Thus, consider -// that thread-local values are always leaked on library unload, or on -// program exit. -// -// [1] http://stackoverflow.com/questions/14538159/about-tls-callback-in-windows - -class ThreadStore { -public: - // Type of a function used to destroy a thread-specific value that - // was previously assigned by calling set(). - typedef void (Destructor)(void* value); - - // Initialize instance so that is hold keys that must be destroyed - // on thread exit by calling |destroy|. - explicit ThreadStore(Destructor* destroy); - - // NOTE: Destructor don't free the thread-local values, but are required - // to avoid crashes (see note above). - ~ThreadStore(); - - // Retrieve current thread-specific value from store. -#ifdef _WIN32 - void* get() const; -#else - inline void* get() const { - return pthread_getspecific(mKey); - } -#endif - - // Set the new thread-specific value. -#ifdef _WIN32 - void set(void* value); -#else - inline void set(void* value) { - pthread_setspecific(mKey, value); - } -#endif - -#ifdef _WIN32 - // Each thread should call this function on exit to ensure that - // all corresponding TLS values are properly freed. - static void OnThreadExit(); -#else - // Nothing to do on Posix. - static inline void OnThreadExit() {} -#endif - -private: - // Ensure you can't create an empty ThreadStore instance, or simply - // copy it in any way. - ThreadStore(); - ThreadStore(const ThreadStore&); - ThreadStore& operator=(const ThreadStore&); - -#ifdef _WIN32 - int mKey; -#else - pthread_key_t mKey; -#endif -}; - -} // namespace emugl - -#endif // EMUGL_COMMON_THREAD_STORE_H diff --git a/emulator/opengl/shared/emugl/common/thread_store_unittest.cpp b/emulator/opengl/shared/emugl/common/thread_store_unittest.cpp deleted file mode 100644 index 6b5dddb96..000000000 --- a/emulator/opengl/shared/emugl/common/thread_store_unittest.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/thread_store.h" - -#include "emugl/common/mutex.h" -#include "emugl/common/testing/test_thread.h" - -#include <gtest/gtest.h> - -namespace emugl { - -namespace { - -// Helper class used to count instance creation and destruction. -class StaticCounter { -public: - enum { - kMaxInstances = 1000, - }; - - StaticCounter() { - Mutex::AutoLock lock(mMutex); - if (mCreationCount < kMaxInstances) - mInstances[mCreationCount] = this; - mCreationCount++; - } - - ~StaticCounter() { - Mutex::AutoLock lock(mMutex); - mDestructionCount++; - } - - static void reset() { - Mutex::AutoLock lock(mMutex); - mCreationCount = 0; - mDestructionCount = 0; - } - - static size_t getCreationCount() { - Mutex::AutoLock lock(mMutex); - return mCreationCount; - } - - static size_t getDestructionCount() { - Mutex::AutoLock lock(mMutex); - return mDestructionCount; - } - - static void freeAll() { - for (size_t n = 0; n < kMaxInstances; ++n) - delete mInstances[n]; - } - -private: - static Mutex mMutex; - static size_t mCreationCount; - static size_t mDestructionCount; - static StaticCounter* mInstances[kMaxInstances]; -}; - -Mutex StaticCounter::mMutex; -size_t StaticCounter::mCreationCount = 0; -size_t StaticCounter::mDestructionCount = 0; -StaticCounter* StaticCounter::mInstances[kMaxInstances]; - -} // namespace - -// Just check that we can create a new ThreadStore with an empty -// destructor, and use it in the current thread. -TEST(ThreadStore, MainThreadWithoutDestructor) { - ThreadStore store(NULL); - static int x = 42; - store.set(&x); - EXPECT_EQ(&x, store.get()); -} - -// The following test checks that exiting a thread correctly deletes -// any thread-local value stored in it. -static void simplyDestroy(void* value) { - delete (StaticCounter*) value; -} - -static void* simpleThreadFunc(void* param) { - ThreadStore* store = static_cast<ThreadStore*>(param); - store->set(new StaticCounter()); - ThreadStore::OnThreadExit(); - return NULL; -} - -TEST(ThreadStore, ThreadsWithDestructor) { - ThreadStore store(simplyDestroy); - const size_t kNumThreads = 1000; - TestThread* threads[kNumThreads]; - StaticCounter::reset(); - - for (size_t n = 0; n < kNumThreads; ++n) { - threads[n] = new TestThread(&simpleThreadFunc, &store); - } - for (size_t n = 0; n < kNumThreads; ++n) { - threads[n]->join(); - } - - EXPECT_EQ(kNumThreads, StaticCounter::getCreationCount()); - EXPECT_EQ(kNumThreads, StaticCounter::getDestructionCount()); - - for (size_t n = 0; n < kNumThreads; ++n) { - delete threads[n]; - } -} - -TEST(ThreadStore, ThreadsWithoutDestructor) { - ThreadStore store(NULL); - const size_t kNumThreads = 1000; - TestThread* threads[kNumThreads]; - StaticCounter::reset(); - - for (size_t n = 0; n < kNumThreads; ++n) { - threads[n] = new TestThread(&simpleThreadFunc, &store); - } - for (size_t n = 0; n < kNumThreads; ++n) { - threads[n]->join(); - } - - EXPECT_EQ(kNumThreads, StaticCounter::getCreationCount()); - EXPECT_EQ(0U, StaticCounter::getDestructionCount()); - - StaticCounter::freeAll(); - - for (size_t n = 0; n < kNumThreads; ++n) { - delete threads[n]; - } -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/thread_unittest.cpp b/emulator/opengl/shared/emugl/common/thread_unittest.cpp deleted file mode 100644 index db1931fe3..000000000 --- a/emulator/opengl/shared/emugl/common/thread_unittest.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/thread.h" - -#include "emugl/common/mutex.h" - -#include <gtest/gtest.h> - -namespace emugl { - -namespace { - -// A simple thread instance that does nothing at all and exits immediately. -class EmptyThread : public ::emugl::Thread { -public: - intptr_t main() { return 42; } -}; - -class CountingThread : public ::emugl::Thread { -public: - class State { - public: - State() : mLock(), mCount(0) {} - ~State() {} - - void increment() { - mLock.lock(); - mCount++; - mLock.unlock(); - } - - int count() const { - int ret; - mLock.lock(); - ret = mCount; - mLock.unlock(); - return ret; - } - - private: - mutable Mutex mLock; - int mCount; - }; - - CountingThread(State* state) : mState(state) {} - - intptr_t main() { - mState->increment(); - return 0; - } - -private: - State* mState; -}; - -} // namespace - -TEST(ThreadTest, SimpleThread) { - Thread* thread = new EmptyThread(); - EXPECT_TRUE(thread); - EXPECT_TRUE(thread->start()); - intptr_t status; - EXPECT_TRUE(thread->wait(&status)); - EXPECT_EQ(42, status); -} - -TEST(ThreadTest, MultipleThreads) { - CountingThread::State state; - const size_t kMaxThreads = 100; - Thread* threads[kMaxThreads]; - - // Create all threads. - for (size_t n = 0; n < kMaxThreads; ++n) { - threads[n] = new CountingThread(&state); - EXPECT_TRUE(threads[n]) << "thread " << n; - } - - // Start them all. - for (size_t n = 0; n < kMaxThreads; ++n) { - EXPECT_TRUE(threads[n]->start()) << "thread " << n; - } - - // Wait for them all. - for (size_t n = 0; n < kMaxThreads; ++n) { - EXPECT_TRUE(threads[n]->wait(NULL)) << "thread " << n; - } - - // Check state. - EXPECT_EQ((int)kMaxThreads, state.count()); - - // Delete them all. - for (size_t n = 0; n < kMaxThreads; ++n) { - delete threads[n]; - } -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/thread_win32.cpp b/emulator/opengl/shared/emugl/common/thread_win32.cpp deleted file mode 100644 index f348ca8ec..000000000 --- a/emulator/opengl/shared/emugl/common/thread_win32.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/thread.h" - -#include "emugl/common/thread_store.h" - -namespace emugl { - -namespace { - -class ScopedLocker { -public: - ScopedLocker(CRITICAL_SECTION* section) : mSection(section) { - EnterCriticalSection(mSection); - } - - ~ScopedLocker() { - LeaveCriticalSection(mSection); - } -private: - CRITICAL_SECTION* mSection; -}; - -} // namespace - -Thread::Thread() : - mThread(INVALID_HANDLE_VALUE), - mThreadId(0), - mExitStatus(0), - mIsRunning(false) { - InitializeCriticalSection(&mLock); -} - -Thread::~Thread() { - if(mThread != INVALID_HANDLE_VALUE) { - CloseHandle(mThread); - } - DeleteCriticalSection(&mLock); -} - -bool Thread::start() { - ScopedLocker locker(&mLock); - - bool ret = true; - mIsRunning = true; - mThread = CreateThread(NULL, 0, &Thread::thread_main, this, 0, &mThreadId); - if (!mThread) { - ret = false; - mIsRunning = false; - } - return ret; -} - -bool Thread::wait(intptr_t* exitStatus) { - { - ScopedLocker locker(&mLock); - if (!mIsRunning) { - // Thread already stopped. - if (exitStatus) { - *exitStatus = mExitStatus; - } - return true; - } - } - - // NOTE: Do not hold lock during wait to aloow thread_main to - // properly update mIsRunning and mExitStatus on thread exit. - if (WaitForSingleObject(mThread, INFINITE) == WAIT_FAILED) { - return false; - } - - if (exitStatus) { - ScopedLocker locker(&mLock); - *exitStatus = mExitStatus; - } - return true; -} - -bool Thread::tryWait(intptr_t* exitStatus) { - ScopedLocker locker(&mLock); - - if (!mIsRunning || - WaitForSingleObject(mThread, 0) != WAIT_OBJECT_0) { - return false; - } - - if (exitStatus) { - *exitStatus = mExitStatus; - } - return true; -} - -// static -DWORD WINAPI Thread::thread_main(void *arg) -{ - Thread* self = reinterpret_cast<Thread*>(arg); - intptr_t ret = self->main(); - - EnterCriticalSection(&self->mLock); - self->mIsRunning = false; - self->mExitStatus = ret; - LeaveCriticalSection(&self->mLock); - - // Ensure all thread-local values are released for this thread. - ::emugl::ThreadStore::OnThreadExit(); - - return static_cast<DWORD>(ret); -} - -} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/unique_integer_map.h b/emulator/opengl/shared/emugl/common/unique_integer_map.h deleted file mode 100644 index 720aceb0c..000000000 --- a/emulator/opengl/shared/emugl/common/unique_integer_map.h +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (C) 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 EMUGL_COMMON_UNIQUE_INTEGER_MAP_H -#define EMUGL_COMMON_UNIQUE_INTEGER_MAP_H - -#include "emugl/common/pod_vector.h" - -#include <stdint.h> - -namespace emugl { - -// Helper template class that implements a bi-directional mapping between -// two integer types |A| and |B|. More specifically: -// -// - The map allocates values of type |B| when a key of type |A| is entered -// in the map. -// -// - keys and values cannot be 0, which is reserved (i.e. means 'invalid'). -// -// This is used in EmuGL to map liberal 'void*' values (e.g. EGLimages ones) -// to unique 32-bit IDs that can be written to / read from the wire protocol. -template <typename A, typename B> -class UniqueIntegerMap { -public: - UniqueIntegerMap() : mForwardPairs(), mBackwardPairs() {} - ~UniqueIntegerMap() {} - - // Return true iff the map is empty. - const bool empty() const { return mForwardPairs.empty(); } - - // Return the number of (key,value) pairs in the map. - size_t size() const { return mForwardPairs.size(); } - - // Find the value associated with |key| in the map. - // Returns 0 in case of failure, or if |key| is 0. - B find(const A key) const; - - // Find the key associated with a given |value| in the map. - // Returns 0 if |value| is 0, or in case of failure. - A findKeyFor(const B value) const; - - // Add |key| to the map and return an automatically-allocated - // unique value for it. Return 0 if |key| is 0. - B add(const A key); - - // Delete the entry associated with a given |key|. The - // corresponding value may be recycled by future calls to add(). - void del(const A key); - -private: - typedef struct { - A first; - B second; - } ForwardPair; - - typedef struct { - B first; - A second; - } BackwardPair; - - size_t findKeyIndexPlusOne(const A key) const; - size_t findValueIndexPlusOne(const B value) const; - - B allocValue(); - void freeValue(B value); - - PodVector<ForwardPair> mForwardPairs; - PodVector<BackwardPair> mBackwardPairs; - - B mLastValue; - PodVector<B> mFreeValues; -}; - -template <typename A, typename B> -B UniqueIntegerMap<A,B>::find(const A key) const { - size_t keyIndex = findKeyIndexPlusOne(key); - if (!keyIndex) { - return 0; - } - return mForwardPairs[keyIndex - 1U].second; -} - -template <typename A, typename B> -A UniqueIntegerMap<A,B>::findKeyFor(const B value) const { - size_t valueIndex = findValueIndexPlusOne(value); - if (!valueIndex) { - return 0; - } - return mBackwardPairs[valueIndex - 1U].second; -} - -template <typename A, typename B> -B UniqueIntegerMap<A,B>::add(const A key) { - // Binary search to find the proper insertion point for the key. - // Also checks that the key isn't already in the set. - size_t min = 0; - size_t max = mForwardPairs.size(); - while (min < max) { - size_t mid = min + ((max - min) >> 1); - A midKey = mForwardPairs[mid].first; - if (midKey < key) { - min = mid + 1U; - } else if (midKey > key) { - max = mid; - } else { - // Already in the set. - return 0; - } - } - - // Generate new unique value - B value = allocValue(); - - ForwardPair* pair = mForwardPairs.emplace(min); - pair->first = key; - pair->second = value; - - // Binary search to find proper insertion point for the value. - min = 0; - max = mBackwardPairs.size(); - while (min < max) { - size_t mid = min + ((max - min) >> 1); - B midValue = mBackwardPairs[mid].first; - if (midValue < value) { - min = mid + 1U; - } else { - max = mid; - } - } - - BackwardPair* backPair = mBackwardPairs.emplace(min); - backPair->first = value; - backPair->second = key; - - return value; -} - -template <typename A, typename B> -void UniqueIntegerMap<A,B>::del(const A key) { - size_t keyIndex = findKeyIndexPlusOne(key); - if (!keyIndex) { - return; - } - B value = mForwardPairs[keyIndex - 1U].second; - size_t valueIndex = findValueIndexPlusOne(value); - mForwardPairs.remove(keyIndex - 1U); - mBackwardPairs.remove(valueIndex - 1U); - freeValue(value); -} - -template <typename A, typename B> -size_t UniqueIntegerMap<A,B>::findKeyIndexPlusOne(const A key) const { - // Binary search in forward pair array. - size_t min = 0; - size_t max = mForwardPairs.size(); - while (min < max) { - size_t mid = min + ((max - min) >> 1); - A midKey = mForwardPairs[mid].first; - if (midKey < key) { - min = mid + 1U; - } else if (midKey > key) { - max = mid; - } else { - return mid + 1U; - } - } - return 0U; -} - -template <typename A, typename B> -size_t UniqueIntegerMap<A,B>::findValueIndexPlusOne(const B value) const { - // Binary search in revere pair array. - size_t min = 0; - size_t max = mBackwardPairs.size(); - while (min < max) { - size_t mid = min + ((max - min) >> 1); - B midValue = mBackwardPairs[mid].first; - if (midValue < value) { - min = mid + 1U; - } else if (midValue > value) { - max = mid; - } else { - return mid + 1U; - } - } - return 0U; -} - -template <typename A, typename B> -B UniqueIntegerMap<A,B>::allocValue() { - if (!mFreeValues.empty()) { - B result = mFreeValues[0]; - mFreeValues.pop(); - return result; - } - return ++mLastValue; -} - -template <typename A, typename B> -void UniqueIntegerMap<A,B>::freeValue(B value) { - if (!value) { - return; - } - if (value == mLastValue) { - mLastValue--; - return; - } - mFreeValues.append(value); -} - -} // namespace emugl - -#endif // EMUGL_COMMON_INTEGER_MAP_H diff --git a/emulator/opengl/shared/emugl/common/unique_integer_map_unittest.cpp b/emulator/opengl/shared/emugl/common/unique_integer_map_unittest.cpp deleted file mode 100644 index 8aee01327..000000000 --- a/emulator/opengl/shared/emugl/common/unique_integer_map_unittest.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (C) 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. - -#include "emugl/common/unique_integer_map.h" - -#include <gtest/gtest.h> - -#include <stdio.h> - -namespace emugl { - -typedef UniqueIntegerMap<uintptr_t,uint32_t> MyMap; - -TEST(UniqueIntegerMap, Empty) { - MyMap map; - - EXPECT_TRUE(map.empty()); - EXPECT_EQ(0U, map.size()); - EXPECT_EQ(0U, map.find(0U)); - EXPECT_EQ(0U, map.find(1U)); - EXPECT_EQ(0U, map.find(2U)); - EXPECT_EQ(0U, map.find(4U)); -} - -TEST(UniqueIntegerMap, AddOne) { - MyMap map; - uintptr_t key1 = 1U; - uint32_t val1 = map.add(key1); - - EXPECT_NE(0U, val1); - EXPECT_EQ(val1, map.find(key1)); - EXPECT_EQ(key1, map.findKeyFor(val1)); - - EXPECT_FALSE(map.empty()); - EXPECT_EQ(1U, map.size()); - - EXPECT_EQ(0U, map.find(0)); - EXPECT_EQ(0U, map.findKeyFor(0)); - - EXPECT_EQ(0U, map.find(key1 + 1)); - EXPECT_EQ(0U, map.findKeyFor(val1 + 1)); -} - -TEST(UniqueIntegerMap, AddMultiple) { - MyMap map; - const size_t kCount = 100; - const size_t kKeyMultiplier = 3U; // must be >= 2. - uint32_t values[kCount]; - - for (size_t n = 0; n < kCount; ++n) { - uintptr_t key = 1U + n * kKeyMultiplier; - values[n] = map.add(key); - EXPECT_NE(0U, values[n]) << "key #" << n; - } - - EXPECT_EQ(kCount, map.size()); - - for (size_t n = 0; n < kCount; ++n) { - uintptr_t key = 1U + n * kKeyMultiplier; - EXPECT_EQ(values[n], map.find(key)) << "key #" << n; - EXPECT_EQ(0U, map.find(key + 1U)) << "key #" << n; - } - - for (size_t n = 0; n < kCount; ++n) { - uintptr_t key = 1U + n * kKeyMultiplier; - EXPECT_EQ(key, map.findKeyFor(values[n])); - } -} - -TEST(UniqueIntegerMap, Del) { - MyMap map; - const size_t kCount = 100; - const size_t kKeyMultiplier = 3U; // must be >= 2. - uint32_t values[kCount]; - - for (size_t n = 0; n < kCount; ++n) { - uintptr_t key = 1U + n * kKeyMultiplier; - values[n] = map.add(key); - } - - for (size_t n = 0; n < kCount; ++n) { - uintptr_t key = 1U + n * kKeyMultiplier; - map.del(key); - EXPECT_EQ(kCount - 1U - n, map.size()); - EXPECT_EQ(0U, map.find(key)); - EXPECT_EQ(0U, map.findKeyFor(values[n])); - } - - EXPECT_TRUE(map.empty()); -} - -} // namespace emugl |
