aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2014-02-27 14:44:51 +0100
committerDavid 'Digit' Turner <digit@google.com>2014-03-11 18:03:08 +0100
commit0863e159faa8c8bf7c47deb92a109961e8653e52 (patch)
treea2815aa64c73aae43ab7e54e02bcc0d72bb5a316
parentbfc6160fecf9af96c659ab2474098275af9f042c (diff)
downloadsdk-0863e159faa8c8bf7c47deb92a109961e8653e52.zip
sdk-0863e159faa8c8bf7c47deb92a109961e8653e52.tar.gz
sdk-0863e159faa8c8bf7c47deb92a109961e8653e52.tar.bz2
emulator/opengl: Remove android::Vector<> usage.
This remove the use of android::Vector<> by providing an alternative vector implementation (emugl::PodVector<>) which is heavily based on the emulator version under external/qemu/android/base/containers/PodVector.h. Ultimately the GPU emulation libraries will move under external/qemu/, and the code will be changed to use android::base::PodVector<> instead of emugl::PodVector<>. Change-Id: I9836ed961795c0791115c61e731d15d17f036972
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp6
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h10
-rw-r--r--emulator/opengl/shared/emugl/common/Android.mk2
-rw-r--r--emulator/opengl/shared/emugl/common/pod_vector.cpp151
-rw-r--r--emulator/opengl/shared/emugl/common/pod_vector.h267
-rw-r--r--emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp127
-rw-r--r--emulator/opengl/shared/emugl/common/scoped_pointer_vector.h27
7 files changed, 582 insertions, 8 deletions
diff --git a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
index a054562..a03f8c9 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
+++ b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
@@ -204,9 +204,7 @@ bool ProgramData::attachShader(GLuint shader)
return false;
}
}
- // AKA m_shaders.push_back(), but that has an ambiguous call to insertAt()
- // due to the default parameters. This is the desired insertAt() overload.
- m_shaders.insertAt(shader, m_shaders.size(), 1);
+ m_shaders.append(shader);
return true;
}
@@ -215,7 +213,7 @@ bool ProgramData::detachShader(GLuint shader)
size_t n = m_shaders.size();
for (size_t i = 0; i < n; i++) {
if (m_shaders[i] == shader) {
- m_shaders.removeAt(i);
+ m_shaders.remove(i);
return true;
}
}
diff --git a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h
index 02278a2..713e17e 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h
+++ b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h
@@ -16,6 +16,10 @@
#ifndef _GL_SHARED_GROUP_H_
#define _GL_SHARED_GROUP_H_
+#include "emugl/common/mutex.h"
+#include "emugl/common/pod_vector.h"
+#include "emugl/common/smart_ptr.h"
+
#define GL_API
#ifndef ANDROID
#define GL_APIENTRY
@@ -34,14 +38,12 @@
#include <utils/List.h>
#include <utils/String8.h>
#include "FixedBuffer.h"
-#include "emugl/common/mutex.h"
-#include "emugl/common/smart_ptr.h"
struct BufferData {
BufferData();
BufferData(GLsizeiptr size, void * data);
GLsizeiptr m_size;
- FixedBuffer m_fixedBuffer;
+ FixedBuffer m_fixedBuffer;
};
class ProgramData {
@@ -61,7 +63,7 @@ private:
bool m_initialized;
bool m_locShiftWAR;
- android::Vector<GLuint> m_shaders;
+ emugl::PodVector<GLuint> m_shaders;
public:
enum {
diff --git a/emulator/opengl/shared/emugl/common/Android.mk b/emulator/opengl/shared/emugl/common/Android.mk
index 6a6c169..5f8fecb 100644
--- a/emulator/opengl/shared/emugl/common/Android.mk
+++ b/emulator/opengl/shared/emugl/common/Android.mk
@@ -7,6 +7,7 @@ LOCAL_PATH := $(call my-dir)
commonSources := \
lazy_instance.cpp \
+ pod_vector.cpp \
smart_ptr.cpp \
sockets.cpp \
thread_store.cpp \
@@ -27,6 +28,7 @@ $(call emugl-end-module)
host_commonSources := \
lazy_instance_unittest.cpp \
+ pod_vector_unittest.cpp \
mutex_unittest.cpp \
smart_ptr_unittest.cpp \
thread_store_unittest.cpp \
diff --git a/emulator/opengl/shared/emugl/common/pod_vector.cpp b/emulator/opengl/shared/emugl/common/pod_vector.cpp
new file mode 100644
index 0000000..3fe8f15
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/pod_vector.cpp
@@ -0,0 +1,151 @@
+// 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) {
+ const size_t kMaxSize = maxItemCapacity(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
new file mode 100644
index 0000000..22a8a1d
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/pod_vector.h
@@ -0,0 +1,267 @@
+// 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) {
+ const size_t kMaxCapacity = SIZE_MAX / itemSize;
+ return mBegin + pos * itemSize;
+ }
+
+ const void* itemAt(size_t pos, size_t itemSize) const {
+ const size_t kMaxCapacity = SIZE_MAX / itemSize;
+ 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
new file mode 100644
index 0000000..9ce509a
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp
@@ -0,0 +1,127 @@
+// 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
new file mode 100644
index 0000000..3d263e9
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/scoped_pointer_vector.h
@@ -0,0 +1,27 @@
+// 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