Use memory pools to allocate nodes, renderers, materials and animations 99/54499/8
authorFerran Sole <ferran.sole@samsung.com>
Tue, 15 Dec 2015 14:53:50 +0000 (14:53 +0000)
committerFerran Sole <ferran.sole@samsung.com>
Thu, 17 Dec 2015 11:46:18 +0000 (11:46 +0000)
Use global memory pools to allocate nodes, renderers material and animations
to speed up traversals.

Change-Id: Iee233169e0e40cd3206c82074b9f015f7c7e424c

16 files changed:
dali/internal/common/fixed-size-memory-pool.cpp
dali/internal/common/fixed-size-memory-pool.h
dali/internal/common/memory-pool-object-allocator.h
dali/internal/event/rendering/material-impl.cpp
dali/internal/event/rendering/renderer-impl.cpp
dali/internal/render/common/render-item.cpp
dali/internal/render/common/render-item.h
dali/internal/render/common/render-list.h
dali/internal/update/animation/scene-graph-animation.cpp
dali/internal/update/animation/scene-graph-animation.h
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h
dali/internal/update/rendering/scene-graph-material.cpp
dali/internal/update/rendering/scene-graph-material.h
dali/internal/update/rendering/scene-graph-renderer.cpp
dali/internal/update/rendering/scene-graph-renderer.h

index 8b69193..0594639 100644 (file)
@@ -19,6 +19,7 @@
 #include <dali/internal/common/fixed-size-memory-pool.h>
 
 // INTERNAL HEADERS
+#include <dali/devel-api/threading/mutex.h>
 #include <dali/public-api/common/dali-common.h>
 
 namespace Dali
@@ -74,7 +75,8 @@ struct FixedSizeMemoryPool::Impl
    * @brief Constructor
    */
   Impl( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
-  :  mFixedSize( fixedSize ),
+  :  mMutex(),
+     mFixedSize( fixedSize ),
      mMemoryBlocks( initialCapacity * mFixedSize ),
      mMaximumBlockCapacity( maximumBlockCapacity ),
      mCurrentBlock( &mMemoryBlocks ),
@@ -123,6 +125,8 @@ struct FixedSizeMemoryPool::Impl
     mCurrentBlockSize = 0;
   }
 
+  Mutex mMutex;                       ///< Mutex for thread-safe allocation and deallocation
+
   SizeType mFixedSize;                ///< The size of each allocation in bytes
 
   Block mMemoryBlocks;                ///< Linked list of allocated memory blocks
@@ -147,6 +151,8 @@ FixedSizeMemoryPool::~FixedSizeMemoryPool()
 
 void* FixedSizeMemoryPool::Allocate()
 {
+  Mutex::ScopedLock( mImpl->mMutex );
+
   // First, recycle deleted objects
   if( mImpl->mDeletedObjects )
   {
@@ -171,11 +177,26 @@ void* FixedSizeMemoryPool::Allocate()
 
 void FixedSizeMemoryPool::Free( void* memory )
 {
+  Mutex::ScopedLock( mImpl->mMutex );
+
   // 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;
 }
 
+void* FixedSizeMemoryPool::AllocateThreadSafe()
+{
+  Mutex::ScopedLock( mImpl->mMutex );
+  return Allocate();
+}
+
+void FixedSizeMemoryPool::FreeThreadSafe( void* memory )
+{
+  Mutex::ScopedLock( mImpl->mMutex );
+  Free( memory );
+}
+
+
 } // namespace Internal
 
 } // namespace Dali
index 4389106..a3317ed 100644 (file)
@@ -81,12 +81,26 @@ public:
   void* Allocate();
 
   /**
+   * @brief Thread-safe version of Allocate()
+   *
+   * @return Return the newly allocated memory
+   */
+  void* AllocateThreadSafe();
+
+  /**
    * @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 );
 
+  /**
+   * @brief Thread-safe version of Free()
+   *
+   * @param memory The memory to be deleted. Must have been allocated by this memory pool
+   */
+  void FreeThreadSafe( void* memory );
+
 private:
 
   // Undefined
index 0349cf8..d38aa7d 100644 (file)
@@ -67,6 +67,16 @@ public:
   }
 
   /**
+   * @brief Thread-safe version of Allocate()
+   *
+   * @return Return the allocated object
+   */
+  T* AllocateThreadSafe()
+  {
+    return new ( mPool->AllocateThreadSafe() ) 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
@@ -80,6 +90,16 @@ public:
   }
 
   /**
+   * @brief Thread-safe version of AllocateRaw()
+   *
+   * @return Return the allocated memory block
+   */
+  void* AllocateRawThreadSafe()
+  {
+    return mPool->AllocateThreadSafe();
+  }
+
+  /**
    * @brief Return the object to the memory pool
    *
    * @param object Pointer to the object to delete
@@ -92,6 +112,18 @@ public:
   }
 
   /**
+   * @brief Thread-safe version of Free()
+   *
+   * @param object Pointer to the object to delete
+   */
+  void FreeThreadSafe( T* object )
+  {
+    object->~T();
+
+    mPool->FreeThreadSafe( object );
+  }
+
+  /**
    * @brief Reset the memory pool, unloading all block memory previously allocated
    */
   void ResetMemoryPool()
index 6539d08..054df46 100644 (file)
@@ -638,7 +638,7 @@ void Material::Initialize()
   EventThreadServices& eventThreadServices = GetEventThreadServices();
   SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
 
-  mSceneObject = new SceneGraph::Material();
+  mSceneObject = SceneGraph::Material::New();
   AddMessage( updateManager, updateManager.GetMaterialOwner(), *mSceneObject );
 
   eventThreadServices.RegisterObject( this );
index 027a103..cb7073a 100644 (file)
@@ -267,7 +267,7 @@ void Renderer::Initialize()
   EventThreadServices& eventThreadServices = GetEventThreadServices();
   SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
 
-  mSceneObject = new SceneGraph::Renderer();
+  mSceneObject = SceneGraph::Renderer::New();
   AddMessage( updateManager, updateManager.GetRendererOwner(), *mSceneObject );
 
   eventThreadServices.RegisterObject( this );
index a177ee4..d01bd43 100644 (file)
 #include <dali/internal/render/common/render-item.h>
 
 // INTERNAL INCLUDES
+#include <dali/internal/common/memory-pool-object-allocator.h>
 #include <dali/internal/render/renderers/render-renderer.h>
 
+namespace
+{
+//Memory pool used to allocate new RenderItems. Memory used by this pool will be released when shutting down DALi
+Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::RenderItem> gRenderItemPool;
+}
 namespace Dali
 {
 
@@ -30,6 +36,11 @@ namespace Internal
 namespace SceneGraph
 {
 
+RenderItem* RenderItem::New()
+{
+  return new ( gRenderItemPool.AllocateRaw() ) RenderItem();
+}
+
 RenderItem::RenderItem()
 : mModelViewMatrix( false ),
   mRenderer( NULL ),
@@ -43,6 +54,11 @@ RenderItem::~RenderItem()
 {
 }
 
+void RenderItem::operator delete( void* ptr )
+{
+  gRenderItemPool.Free( static_cast<RenderItem*>( ptr ) );
+}
+
 void RenderItem::Reset()
 {
   mRenderer = NULL;
index 86c1270..b25c9e5 100644 (file)
@@ -50,9 +50,9 @@ class RenderItem
 public:
 
   /**
-   * Create a new render-item.
+   * Construct a new RenderItem
    */
-  RenderItem();
+  static RenderItem* New();
 
   /**
    * Non-virtual destructor; RenderItem is not suitable as a base class.
@@ -60,6 +60,12 @@ public:
   ~RenderItem();
 
   /**
+   * Overriden delete operator.
+   * Deletes the RenderItem from its global memory pool
+   */
+  void operator delete( void* ptr );
+
+  /**
    * Reset the render-item.
    */
   void Reset();
@@ -132,6 +138,11 @@ public:
 
 private:
 
+  /**
+   * Private constructor. See RenderItem::New
+   */
+  RenderItem();
+
   // RenderItems should not be copied as they are heavy
   RenderItem( const RenderItem& item );
   RenderItem& operator = ( const RenderItem& item );
index fef087d..3e72c31 100644 (file)
@@ -162,7 +162,7 @@ public:
     // check if we have enough items, we can only be one behind at worst
     if( mItems.Count() <= mNextFree )
     {
-      mItems.PushBack( new RenderItem ); // Push a new empty render item
+      mItems.PushBack( RenderItem::New() ); // Push a new empty render item
     }
     // get the item mNextFree points to and increase by one
     RenderItem& item = *mItems[ mNextFree++ ];
index a2538d1..207d5b4 100644 (file)
 #include <cmath> // fmod
 
 // INTERNAL INCLUDES
+#include <dali/internal/common/memory-pool-object-allocator.h>
 #include <dali/internal/render/common/performance-monitor.h>
 
+namespace //Unnamed namespace
+{
+//Memory pool used to allocate new animations. Memory used by this pool will be released when shutting down DALi
+Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::Animation> gAnimationMemoryPool;
+}
+
 namespace Dali
 {
 
@@ -33,6 +40,10 @@ namespace Internal
 namespace SceneGraph
 {
 
+Animation* Animation::New( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction disconnectAction )
+{
+  return new ( gAnimationMemoryPool.AllocateRawThreadSafe() ) Animation( durationSeconds, speedFactor, playRange, isLooping, endAction, disconnectAction );
+}
 
 Animation::Animation( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, Dali::Animation::EndAction endAction, Dali::Animation::EndAction disconnectAction )
 : mDurationSeconds(durationSeconds),
@@ -51,6 +62,11 @@ Animation::~Animation()
 {
 }
 
+void Animation::operator delete( void* ptr )
+{
+  gAnimationMemoryPool.FreeThreadSafe( static_cast<Animation*>( ptr ) );
+}
+
 void Animation::SetDuration(float durationSeconds)
 {
   mDurationSeconds = durationSeconds;
index c00a21e..94d42f0 100644 (file)
@@ -71,10 +71,7 @@ public:
    * @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected.
    * @return A new Animation
    */
-  static Animation* New( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction disconnectAction )
-  {
-    return new Animation( durationSeconds, speedFactor, playRange, isLooping, endAction, disconnectAction );
-  }
+  static Animation* New( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction disconnectAction );
 
   /**
    * Virtual destructor
@@ -82,6 +79,12 @@ public:
   virtual ~Animation();
 
   /**
+   * Overriden delete operator
+   * Deletes the animation from its global memory pool
+   */
+  void operator delete( void* ptr );
+
+  /**
    * Set the duration of an animation.
    * @pre durationSeconds must be greater than zero.
    * @param[in] durationSeconds The duration in seconds.
index 9a4ce2d..d78eaa3 100644 (file)
 #include <dali/internal/update/nodes/node.h>
 
 // INTERNAL INCLUDES
+#include <dali/internal/common/internal-constants.h>
+#include <dali/internal/common/memory-pool-object-allocator.h>
 #include <dali/internal/update/node-attachments/node-attachment.h>
 #include <dali/internal/update/common/discard-queue.h>
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/common/constants.h>
-#include <dali/internal/common/internal-constants.h>
+
+namespace //Unnamed namespace
+{
+//Memory pool used to allocate new nodes. Memory used by this pool will be released when shutting down DALi
+Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::Node> gNodeMemoryPool;
+}
 
 namespace Dali
 {
@@ -39,7 +46,7 @@ const ColorMode Node::DEFAULT_COLOR_MODE( USE_OWN_MULTIPLY_PARENT_ALPHA );
 
 Node* Node::New()
 {
-  return new Node();
+  return new ( gNodeMemoryPool.AllocateRawThreadSafe() ) Node();
 }
 
 Node::Node()
@@ -79,6 +86,11 @@ Node::~Node()
 {
 }
 
+void Node::operator delete( void* ptr )
+{
+  gNodeMemoryPool.FreeThreadSafe( static_cast<Node*>( ptr ) );
+}
+
 void Node::OnDestroy()
 {
   // Node attachments should be notified about the disconnection.
index 0be8c50..1cf0ae1 100644 (file)
@@ -112,6 +112,12 @@ public:
   virtual ~Node();
 
   /**
+   * Overriden delete operator
+   * Deletes the node from its global memory pool
+   */
+  void operator delete( void* ptr );
+
+  /**
    * When a Node is marked "active" it has been disconnected, but its properties have been modified.
    * @note An inactive Node will be skipped during the UpdateManager ResetProperties stage.
    * @param[in] isActive True if the Node is active.
index acd9ab7..ee4b79b 100644 (file)
 #include <dali/internal/update/resources/texture-metadata.h>
 #include <dali/internal/update/resources/resource-manager.h>
 #include <dali/internal/render/shaders/scene-graph-shader.h>
+#include <dali/internal/common/memory-pool-object-allocator.h>
+
+namespace //Unnamed namespace
+{
+//Memory pool used to allocate new materials. Memory used by this pool will be released when shutting down DALi
+Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::Material> gMaterialMemoryPool;
+}
 
 namespace Dali
 {
@@ -35,6 +42,11 @@ namespace Internal
 namespace SceneGraph
 {
 
+Material* Material::New()
+{
+  return new ( gMaterialMemoryPool.AllocateRawThreadSafe() ) Material();
+}
+
 Material::Material()
 : mShader( NULL ),
   mBlendColor( NULL ),
@@ -59,6 +71,11 @@ Material::~Material()
   mConnectionObservers.Destroy( *this );
 }
 
+void Material::operator delete( void* ptr )
+{
+  gMaterialMemoryPool.FreeThreadSafe( static_cast<Material*>( ptr ) );
+}
+
 void Material::Prepare( const ResourceManager& resourceManager )
 {
   if( mMaterialChanged )
index 743d516..01072db 100644 (file)
@@ -61,9 +61,9 @@ public:
   };
 
   /**
-   * Constructor
+   * Construct a new Material.
    */
-  Material();
+  static Material* New();
 
   /**
    * Destructor
@@ -71,6 +71,12 @@ public:
   virtual ~Material();
 
   /**
+   * Overriden delete operator
+   * Deletes the material from its global memory pool
+   */
+  void operator delete( void* ptr );
+
+  /**
    * Prepare material, check texture loading status, opacity etc
    * @param resourceManager for checking texture details and loading status
    */
@@ -270,6 +276,13 @@ public: // ConnectionChangePropagator::Observer
    */
   virtual void ConnectedUniformMapChanged();
 
+private:
+
+  /**
+   * Protected constructor; See also Material::New()
+   */
+   Material();
+
 private: // Data
 
   Shader*                         mShader;
index ed67003..7e7eb7b 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali/internal/update/nodes/node.h>
 #include <dali/internal/render/queue/render-queue.h>
 #include <dali/internal/common/internal-constants.h>
+#include <dali/internal/common/memory-pool-object-allocator.h>
 
 
 namespace // unnamed namespace
@@ -38,6 +39,9 @@ const unsigned int UNIFORM_MAP_READY      = 0;
 const unsigned int COPY_UNIFORM_MAP       = 1;
 const unsigned int REGENERATE_UNIFORM_MAP = 2;
 
+//Memory pool used to allocate new renderers. Memory used by this pool will be released when shutting down DALi
+Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::Renderer> gRendererMemoryPool;
+
 void AddMappings( Dali::Internal::SceneGraph::CollectedUniformMap& localMap, const Dali::Internal::SceneGraph::UniformMap& uniformMap )
 {
   // Iterate thru uniformMap.
@@ -92,6 +96,11 @@ namespace Internal
 namespace SceneGraph
 {
 
+Renderer* Renderer::New()
+{
+  return new ( gRendererMemoryPool.AllocateRawThreadSafe() ) Renderer();
+}
+
 Renderer::Renderer()
 :mSceneController(0),
  mRenderer(NULL),
@@ -126,6 +135,12 @@ Renderer::~Renderer()
   }
 }
 
+void Renderer::operator delete( void* ptr )
+{
+  gRendererMemoryPool.FreeThreadSafe( static_cast<Renderer*>( ptr ) );
+}
+
+
 void Renderer::PrepareRender( BufferIndex updateBufferIndex )
 {
   mResourcesReady = false;
index b2a4517..610b8ce 100644 (file)
@@ -62,9 +62,9 @@ public:
   };
 
   /**
-   * Default constructor
+   * Construct a new Renderer
    */
-  Renderer();
+  static Renderer* New();
 
   /**
    * Destructor
@@ -72,6 +72,12 @@ public:
   virtual ~Renderer();
 
   /**
+   * Overriden delete operator
+   * Deletes the renderer from its global memory pool
+   */
+  void operator delete( void* ptr );
+
+  /**
    * Set the material for the renderer
    * @param[in] bufferIndex The current frame's buffer index
    * @param[in] material The material this renderer will use
@@ -242,6 +248,11 @@ public: // From UniformMapDataProvider
 private:
 
   /**
+   * Protected constructor; See also Renderer::New()
+   */
+  Renderer();
+
+  /**
    * Helper function to create a new render data provider
    * @return the new (initialized) data provider
    */