add missing files
[ardour.git] / libs / pbd / pbd / pool.h
index e8ad780dc2a6052a115d4dabc5f1569358a7638f..58c5861d23341260dabdd9b4a5c71cdea13a0a61 100644 (file)
 #include <vector>
 #include <string>
 
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
 
 #include "pbd/ringbuffer.h"
 
+/** A pool of data items that can be allocated, read from and written to
+ *  without system memory allocation or locking.
+ */
 class Pool 
 {
   public:
@@ -39,11 +42,11 @@ class Pool
        std::string name() const { return _name; }
 
   protected:
-       RingBuffer<void*> free_list;
+       RingBuffer<void*> free_list; ///< a list of pointers to free items within block
        std::string _name;
 
   private:
-       void *block;
+       void *block; ///< data storage area
 };
 
 class SingleAllocMultiReleasePool : public Pool
@@ -56,7 +59,7 @@ class SingleAllocMultiReleasePool : public Pool
        virtual void release (void *);
 
   private:
-    Glib::Mutex* m_lock;
+        Glib::Threads::Mutex m_lock;
 };
 
 
@@ -70,36 +73,67 @@ class MultiAllocSingleReleasePool : public Pool
        virtual void release (void *);
 
   private:
-    Glib::Mutex* m_lock;
+        Glib::Threads::Mutex m_lock;
 };
 
+class PerThreadPool;
+
+/** Management of a per-thread pool of data that is allocated by one thread and
+ *  freed by one other thread. Not safe for use when there is more than 1
+ *  reader and 1 writer. 
+ *
+ *  This is basically a wrapper around a thread-local storage instance of a 
+ *  ringbuffer, made safe for use in the case where multiple threads allocate
+ *  from the ringbuffer and a single thread "frees" the allocations.
+ * 
+ *  Rather than using locks, each thread has its own ringbuffer (and associated
+ *  data), and so it calls alloc(), passes a pointer to the result of the alloc
+ *  to another thread, which later calls push() to "free" it. 
+ */
 class CrossThreadPool : public Pool
 {
   public:
-       CrossThreadPool (std::string n, unsigned long isize, unsigned long nitems);
+       CrossThreadPool (std::string n, unsigned long isize, unsigned long nitems, PerThreadPool *);
 
        void* alloc ();
        void push (void *);
+
+       PerThreadPool* parent () const {
+               return _parent;
+       }
+
+       bool empty ();
        
   private:
        RingBuffer<void*> pending;
+       PerThreadPool* _parent;
 };
 
+/** A class to manage per-thread pools of memory.  One object of this class is instantiated,
+ *  and then it is used to create per-thread pools for 1 or more threads as required.
+ */
 class PerThreadPool
 {
   public:
        PerThreadPool ();
 
-       GPrivate* key() const { return _key; }
+        const Glib::Threads::Private<CrossThreadPool>& key() const { return _key; }
 
        void  create_per_thread_pool (std::string name, unsigned long item_size, unsigned long nitems);
        CrossThreadPool* per_thread_pool ();
-       
+
+       void set_trash (RingBuffer<CrossThreadPool*>* t);
+       void add_to_trash (CrossThreadPool *);
+
   private:
-       GPrivate* _key;
+        Glib::Threads::Private<CrossThreadPool> _key;
        std::string _name;
        unsigned long _item_size;
        unsigned long _nitems;
+
+       /** mutex to protect either changes to the _trash variable, or writes to the RingBuffer */
+        Glib::Threads::Mutex _trash_mutex;
+       RingBuffer<CrossThreadPool*>* _trash;
 };
 
 #endif // __qm_pool_h__