utc-Dali-DynamicsWorld.cpp
utc-Dali-DynamicsWorldConfig.cpp
utc-Dali-EncodedBufferImage.cpp
+ utc-Dali-FixedSizeMemoryPool.cpp
utc-Dali-Font.cpp
utc-Dali-FontParameters.cpp
utc-Dali-FrameBufferImage.cpp
utc-Dali-MathUtils.cpp
utc-Dali-Matrix.cpp
utc-Dali-Matrix3.cpp
+ utc-Dali-MemoryPoolObjectAllocator.cpp
utc-Dali-MeshActor.cpp
utc-Dali-MeshData.cpp
utc-Dali-Model.cpp
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_fixedsizememorypool_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void utc_dali_fixedsizememorypool_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+int gTestObjectConstructed = 0;
+int gTestObjectDestructed = 0;
+int gTestObjectMethod = 0;
+int gTestObjectDataAccess = 0;
+
+} // namespace
+
+
+class TestObject
+{
+public:
+
+ TestObject()
+ : mData1( 0 ),
+ mData2( false )
+ {
+ gTestObjectConstructed++;
+ }
+
+ ~TestObject()
+ {
+ gTestObjectDestructed++;
+ }
+
+ void Method()
+ {
+ gTestObjectMethod++;
+ }
+
+ void DataAccess()
+ {
+ mData1++;
+ mData2 = true;
+
+ gTestObjectDataAccess++;
+ }
+
+private:
+
+ int mData1;
+ bool mData2;
+
+};
+
+int UtcDaliFixedSizeMemoryPoolCreate(void)
+{
+ gTestObjectConstructed = 0;
+ gTestObjectDestructed = 0;
+ gTestObjectMethod = 0;
+ gTestObjectDataAccess = 0;
+
+ FixedSizeMemoryPool memoryPool( TypeSizeWithAlignment< TestObject >::size );
+
+ TestObject* testObject1 = new (memoryPool.Allocate()) TestObject();
+ DALI_TEST_CHECK( testObject1 );
+ DALI_TEST_EQUALS( gTestObjectConstructed, 1, TEST_LOCATION );
+
+ testObject1->Method();
+ DALI_TEST_EQUALS( gTestObjectMethod, 1, TEST_LOCATION );
+
+ testObject1->DataAccess();
+ DALI_TEST_EQUALS( gTestObjectDataAccess, 1, TEST_LOCATION );
+
+ testObject1->~TestObject();
+ memoryPool.Free( testObject1 );
+ DALI_TEST_EQUALS( gTestObjectDestructed, 1, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliFixedSizeMemoryPoolStressTest(void)
+{
+ gTestObjectConstructed = 0;
+ gTestObjectDestructed = 0;
+ gTestObjectMethod = 0;
+ gTestObjectDataAccess = 0;
+
+ const size_t initialCapacity = 32;
+ const size_t maximumCapacity = 1024;
+
+ const unsigned int numObjects = 1024 * 1024;
+
+ FixedSizeMemoryPool memoryPool( TypeSizeWithAlignment< TestObject >::size, initialCapacity, maximumCapacity );
+
+ Dali::Vector<TestObject*> objects;
+ objects.Reserve( numObjects );
+
+ for( unsigned int i = 0; i < numObjects; ++i )
+ {
+ TestObject* testObject = new ( memoryPool.Allocate() ) TestObject();
+ DALI_TEST_CHECK( testObject );
+
+ objects.PushBack( testObject );
+ }
+
+ DALI_TEST_EQUALS( gTestObjectConstructed, numObjects, TEST_LOCATION );
+
+ for( unsigned int i = 0; i < numObjects; ++i )
+ {
+ objects[i]->~TestObject();
+ memoryPool.Free( objects[i] );
+ }
+
+ DALI_TEST_EQUALS( gTestObjectDestructed, numObjects, TEST_LOCATION );
+
+ END_TEST;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_memorypoolobjectallocator_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void utc_dali_memorypoolobjectallocator_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+struct MemoryPoolObjectAllocatorTestObjectTracking
+{
+ int testObjectDestructed;
+ int testObjectMethod;
+ int testObjectDataAccess;
+
+ MemoryPoolObjectAllocatorTestObjectTracking()
+ : testObjectDestructed( 0 ),
+ testObjectMethod( 0 ),
+ testObjectDataAccess( 0 )
+ {
+ }
+};
+
+class MemoryPoolObjectAllocatorTestObject
+{
+public:
+
+ MemoryPoolObjectAllocatorTestObject()
+ : mData1( 0 ),
+ mData2( false ),
+ mTracking( NULL )
+ {
+ }
+
+ ~MemoryPoolObjectAllocatorTestObject()
+ {
+ if( mTracking )
+ {
+ mTracking->testObjectDestructed++;
+ }
+ }
+
+ void Method()
+ {
+ if( mTracking )
+ {
+ mTracking->testObjectMethod++;
+ }
+ }
+
+ void DataAccess()
+ {
+ mData1++;
+ mData2 = true;
+
+ if( mTracking )
+ {
+ mTracking->testObjectDataAccess++;
+ }
+ }
+
+ void SetTracking( MemoryPoolObjectAllocatorTestObjectTracking* tracking )
+ {
+ mTracking = tracking;
+ }
+
+private:
+
+ int mData1;
+ bool mData2;
+
+ MemoryPoolObjectAllocatorTestObjectTracking* mTracking;
+};
+
+int UtcDaliMemoryPoolObjectAllocatorObjectAllocation(void)
+{
+
+ MemoryPoolObjectAllocator< MemoryPoolObjectAllocatorTestObject > allocator;
+
+ // Allocate an object
+ MemoryPoolObjectAllocatorTestObject* testObject1 = allocator.Allocate();
+ DALI_TEST_CHECK( testObject1 );
+
+ MemoryPoolObjectAllocatorTestObjectTracking tracking1;
+ testObject1->SetTracking( &tracking1 );
+
+ testObject1->Method();
+ DALI_TEST_EQUALS( tracking1.testObjectMethod, 1, TEST_LOCATION );
+
+ testObject1->DataAccess();
+ DALI_TEST_EQUALS( tracking1.testObjectDataAccess, 1, TEST_LOCATION );
+
+ allocator.Free( testObject1 );
+ DALI_TEST_EQUALS( tracking1.testObjectDestructed, 1, TEST_LOCATION );
+
+ // Reset and allocate another object
+ allocator.ResetMemoryPool();
+
+ MemoryPoolObjectAllocatorTestObject* testObject2 = allocator.Allocate();
+ DALI_TEST_CHECK( testObject2 );
+
+ MemoryPoolObjectAllocatorTestObjectTracking tracking2;
+ testObject2->SetTracking( &tracking2 );
+
+ testObject2->Method();
+ DALI_TEST_EQUALS( tracking2.testObjectMethod, 1, TEST_LOCATION );
+
+ testObject2->DataAccess();
+ DALI_TEST_EQUALS( tracking2.testObjectDataAccess, 1, TEST_LOCATION );
+
+ allocator.Free( testObject2 );
+ DALI_TEST_EQUALS( tracking2.testObjectDestructed, 1, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliMemoryPoolObjectAllocatorObjectRawAllocation(void)
+{
+ MemoryPoolObjectAllocator< MemoryPoolObjectAllocatorTestObject > allocator;
+
+ MemoryPoolObjectAllocatorTestObject* testObject = new ( allocator.AllocateRaw() ) MemoryPoolObjectAllocatorTestObject();
+ DALI_TEST_CHECK( testObject );
+
+ MemoryPoolObjectAllocatorTestObjectTracking tracking;
+ testObject->SetTracking( &tracking );
+
+ testObject->Method();
+ DALI_TEST_EQUALS( tracking.testObjectMethod, 1, TEST_LOCATION );
+
+ testObject->DataAccess();
+ DALI_TEST_EQUALS( tracking.testObjectDataAccess, 1, TEST_LOCATION );
+
+ allocator.Free( testObject );
+ DALI_TEST_EQUALS( tracking.testObjectDestructed, 1, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliMemoryPoolObjectAllocatorObjectAllocationPOD(void)
+{
+ MemoryPoolObjectAllocator< bool > allocator;
+
+ bool* testObject1 = allocator.Allocate();
+ DALI_TEST_CHECK( testObject1 );
+
+ allocator.Free( testObject1 );
+
+ allocator.ResetMemoryPool();
+
+ bool* testObject2 = allocator.Allocate();
+ DALI_TEST_CHECK( testObject2 );
+
+ allocator.Free( testObject2 );
+
+ END_TEST;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/common/fixed-size-memory-pool.h>
+
+// INTERNAL HEADERS
+#include <dali/public-api/dali-core.h>
+
+namespace Dali
+{
+
+/**
+ * @brief Private implementation class
+ */
+struct FixedSizeMemoryPool::Impl
+{
+ /**
+ * @brief Struct to represent a block of memory from which allocations can be made.
+ *
+ * The block forms a linked list.
+ */
+ struct Block
+ {
+ void* blockMemory; ///< The allocated memory from which allocations can be made
+ Block* nextBlock; ///< The next block in the linked list
+
+ /**
+ * @brief Construct a new block with given size
+ *
+ * @param size The size of the memory block to allocate in bytes. Must be non-zero.
+ */
+ Block( SizeType size )
+ : nextBlock( NULL )
+ {
+ blockMemory = ::operator new( size );
+ DALI_ASSERT_ALWAYS( blockMemory && "Out of memory" );
+ }
+
+ /**
+ * @brief Destructor
+ */
+ ~Block()
+ {
+ ::operator delete( blockMemory );
+ }
+ };
+
+ /**
+ * @brief Constructor
+ */
+ Impl( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
+ : mFixedSize( fixedSize ),
+ mMemoryBlocks( initialCapacity * mFixedSize ),
+ mMaximumBlockCapacity( maximumBlockCapacity ),
+ mCurrentBlock( &mMemoryBlocks ),
+ mCurrentBlockCapacity( initialCapacity ),
+ mCurrentBlockSize( 0 ),
+ mDeletedObjects( NULL )
+ {
+ // We need enough room to store the deleted list in the data
+ DALI_ASSERT_DEBUG( mFixedSize >= sizeof( void* ) );
+ }
+
+ /**
+ * @brief Destructor
+ */
+ ~Impl()
+ {
+ // Clean up memory block linked list (mMemoryBlocks will be auto-destroyed by its destructor)
+ Block* block = mMemoryBlocks.nextBlock;
+ while( block )
+ {
+ Block* nextBlock = block->nextBlock;
+ delete block;
+ block = nextBlock;
+ }
+ }
+
+ /**
+ * @brief Allocate a new block for allocating memory from
+ */
+ void AllocateNewBlock()
+ {
+ // Double capacity for the new block
+ SizeType size = mCurrentBlockCapacity * 2;
+ if( size > mMaximumBlockCapacity || size < mCurrentBlockCapacity ) // Check for overflow of size type
+ {
+ size = mMaximumBlockCapacity;
+ }
+
+ mCurrentBlockCapacity = size;
+
+ // Allocate
+ Block* block = new Block( mCurrentBlockCapacity * mFixedSize );
+ mCurrentBlock->nextBlock = block; // Add to end of linked list
+ mCurrentBlock = block;
+
+ mCurrentBlockSize = 0;
+ }
+
+ SizeType mFixedSize; ///< The size of each allocation in bytes
+
+ Block mMemoryBlocks; ///< Linked list of allocated memory blocks
+ SizeType mMaximumBlockCapacity; ///< The maximum allowed capacity of allocations in a new memory block
+
+ Block* mCurrentBlock; ///< Pointer to the active block
+ SizeType mCurrentBlockCapacity; ///< The maximum number of allocations that can be allocated for the current block
+ SizeType mCurrentBlockSize; ///< The number of allocations allocated to the current block
+
+ void* mDeletedObjects; ///< Pointer to the head of the list of deleted objects. The addresses are stored in the allocated memory blocks.
+};
+
+
+
+FixedSizeMemoryPool::FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
+{
+ mImpl = new Impl( fixedSize, initialCapacity, maximumBlockCapacity );
+}
+
+FixedSizeMemoryPool::~FixedSizeMemoryPool()
+{
+ delete mImpl;
+}
+
+void* FixedSizeMemoryPool::Allocate()
+{
+ // First, recycle deleted objects
+ if( mImpl->mDeletedObjects )
+ {
+ void* recycled = mImpl->mDeletedObjects;
+ mImpl->mDeletedObjects = *( reinterpret_cast< void** >( mImpl->mDeletedObjects ) ); // Pop head off front of deleted objects list
+ return recycled;
+ }
+
+ // Check if current block is full
+ if( mImpl->mCurrentBlockSize >= mImpl->mCurrentBlockCapacity )
+ {
+ mImpl->AllocateNewBlock();
+ }
+
+ // Placement new the object in block memory
+ unsigned char* objectAddress = static_cast< unsigned char* >( mImpl->mCurrentBlock->blockMemory );
+ objectAddress += mImpl->mCurrentBlockSize * mImpl->mFixedSize;
+ mImpl->mCurrentBlockSize++;
+
+ return objectAddress;
+}
+
+void FixedSizeMemoryPool::Free( void* memory )
+{
+ // Add memory to head of deleted objects list. Store next address in the same memory space as the old object.
+ *( reinterpret_cast< void** >( memory ) ) = mImpl->mDeletedObjects;
+ mImpl->mDeletedObjects = memory;
+}
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_FIXED_SIZE_MEMORY_POOL_H__
+#define __DALI_FIXED_SIZE_MEMORY_POOL_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+#include <cstddef>
+
+namespace Dali
+{
+
+/**
+ * @brief Calculate the size of a type taking alignment into account
+ */
+template< typename T >
+struct TypeSizeWithAlignment
+{
+ ///< The size of the type with alignment taken into account
+ static const size_t size = ( ( sizeof( T ) + sizeof( void* ) - 1 ) / sizeof( void* ) ) * sizeof( void* );
+};
+
+/**
+ * @brief Memory pool for a given fixed size of memory.
+ *
+ * The pool will allocate and reclaim blocks of memory without concern for what is
+ * stored in them. This means it is up to the client to construct/destruct objects
+ * and hence determine what data type is stored in the memory block. See FixedSizeObjectAllocator
+ * below for an example client for creating objects of a given type. It is also up to the client
+ * to ensure that the size of the block takes memory alignment into account for the
+ * type of data they wish to store in the block. The TypeSizeWithAlignment<T> template
+ * can be useful for determining the size of memory aligned blocks for a given type.
+ */
+class FixedSizeMemoryPool
+{
+public:
+
+ typedef uint32_t SizeType;
+
+public:
+
+ /**
+ * @brief Constructor.
+ *
+ * @param fixedSize The fixed size of each memory allocation. Use TypeSizeWithAlignment if aligned memory is required.
+ * @param initialCapacity The initial size of the memory pool. Defaults to a small value (32) after
+ * which the capacity will double as needed.
+ * @param maximumBlockCapacity The maximum size that a new block of memory can be allocated. Defaults to
+ * a large value (1024 * 1024 = 1048576).
+ */
+ explicit FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity = 32, SizeType maximumBlockCapacity = 1048576 );
+
+ /**
+ * @brief Destructor.
+ */
+ ~FixedSizeMemoryPool();
+
+ /**
+ * @brief Allocate a new fixed size block of memory
+ *
+ * @return Return the newly allocated memory
+ */
+ void* Allocate();
+
+ /**
+ * @brief Delete a block of memory for the allocation that has been allocated by this memory pool
+ *
+ * @param memory The memory to be deleted. Must have been allocated by this memory pool
+ */
+ void Free( void* memory );
+
+private:
+
+ struct Impl;
+ Impl* mImpl;
+
+};
+
+
+} // namespace Dali
+
+#endif /* __DALI_FIXED_SIZE_MEMORY_POOL_H__ */
--- /dev/null
+#ifndef __DALI_MEMORY_POOL_OBJECT_ALLOCATOR_H__
+#define __DALI_MEMORY_POOL_OBJECT_ALLOCATOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/fixed-size-memory-pool.h>
+
+namespace Dali
+{
+
+/**
+ * @brief Helper for allocating/deallocating objects using a memory pool.
+ *
+ * This is a helper class for creating and destroying objects of a single given type.
+ * The type may be a class or POD.
+ *
+ */
+template< typename T >
+class MemoryPoolObjectAllocator
+{
+public:
+
+ /**
+ * @brief Constructor
+ */
+ MemoryPoolObjectAllocator()
+ : mPool( NULL )
+ {
+ ResetMemoryPool();
+ }
+
+ /**
+ * @brief Destructor
+ */
+ ~MemoryPoolObjectAllocator()
+ {
+ delete mPool;
+ }
+
+ /**
+ * @brief Allocate from the memory pool
+ *
+ * @return Return the allocated object
+ */
+ T* Allocate()
+ {
+ return new ( mPool->Allocate() ) T();
+ }
+
+ /**
+ * @brief Allocate a block of memory from the memory pool of the appropriate size to
+ * store an object of type T. This is usually so the memory can be used in a
+ * placement new for an object of type T with a constructor that takes multiple
+ * parameters.
+ *
+ * @return Return the allocated memory block
+ */
+ void* AllocateRaw()
+ {
+ return mPool->Allocate();
+ }
+
+ /**
+ * @brief Return the object to the memory pool
+ *
+ * @param object Pointer to the object to delete
+ */
+ void Free( T* object )
+ {
+ object->~T();
+
+ mPool->Free( object );
+ }
+
+ /**
+ * @brief Reset the memory pool, unloading all block memory previously allocated
+ */
+ void ResetMemoryPool()
+ {
+ if( mPool )
+ {
+ delete mPool;
+ }
+
+ mPool = new FixedSizeMemoryPool( TypeSizeWithAlignment< T >::size );
+ }
+
+private:
+
+ FixedSizeMemoryPool* mPool; ///< Memory pool from which allocations are made
+
+};
+
+} // namespace Dali
+
+#endif /* __DALI_MEMORY_POOL_OBJECT_ALLOCATOR_H__ */
#include <dali/public-api/common/constants.h>
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/fixed-size-memory-pool.h>
#include <dali/public-api/common/intrusive-ptr.h>
#include <dali/public-api/common/light.h>
#include <dali/public-api/common/loading-state.h>
+#include <dali/public-api/common/memory-pool-object-allocator.h>
#include <dali/public-api/common/mutex.h>
#include <dali/public-api/common/stage.h>
#include <dali/public-api/common/vector-wrapper.h>
$(public_api_src_dir)/common/constants.cpp \
$(public_api_src_dir)/common/dali-common.cpp \
$(public_api_src_dir)/common/dali-vector.cpp \
+ $(public_api_src_dir)/common/fixed-size-memory-pool.cpp \
$(public_api_src_dir)/common/light.cpp \
$(public_api_src_dir)/common/mutex.cpp \
$(public_api_src_dir)/common/stage.cpp \
$(public_api_src_dir)/common/constants.h \
$(public_api_src_dir)/common/dali-common.h \
$(public_api_src_dir)/common/dali-vector.h \
+ $(public_api_src_dir)/common/fixed-size-memory-pool.h \
$(public_api_src_dir)/common/intrusive-ptr.h \
$(public_api_src_dir)/common/light.h \
$(public_api_src_dir)/common/loading-state.h \
$(public_api_src_dir)/common/mutex.h \
$(public_api_src_dir)/common/map-wrapper.h \
+ $(public_api_src_dir)/common/memory-pool-object-allocator.h \
$(public_api_src_dir)/common/ref-counted-dali-vector.h \
$(public_api_src_dir)/common/set-wrapper.h \
$(public_api_src_dir)/common/scoped-pointer.h \