3 monitor tweaks for the_CLA. shift+click to default, and new preset vals
[ardour.git] / libs / pbd / pbd / pool.h
index d604680ae26d7ce875b3e01fe9464fefa9c306d3..165a3aac4bc95606dd0f12b1263c36b43b34e061 100644 (file)
 #include <vector>
 #include <string>
 
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
 
-#include <pbd/ringbuffer.h>
+#include "pbd/libpbd_visibility.h"
+#include "pbd/ringbuffer.h"
 
-class Pool 
+/** A pool of data items that can be allocated, read from and written to
+ *  without system memory allocation or locking.
+ */
+class LIBPBD_API Pool 
 {
   public:
        Pool (std::string name, unsigned long item_size, unsigned long nitems);
@@ -38,13 +42,15 @@ class Pool
        
        std::string name() const { return _name; }
 
-  private:
-       RingBuffer<void*>* free_list;
+  protected:
+       RingBuffer<void*> free_list; ///< a list of pointers to free items within block
        std::string _name;
-       void *block;
+
+  private:
+       void *block; ///< data storage area
 };
 
-class SingleAllocMultiReleasePool : public Pool
+class LIBPBD_API SingleAllocMultiReleasePool : public Pool
 {
   public:
        SingleAllocMultiReleasePool (std::string name, unsigned long item_size, unsigned long nitems);
@@ -54,11 +60,11 @@ class SingleAllocMultiReleasePool : public Pool
        virtual void release (void *);
 
   private:
-    Glib::Mutex* m_lock;
+        Glib::Threads::Mutex m_lock;
 };
 
 
-class MultiAllocSingleReleasePool : public Pool
+class LIBPBD_API MultiAllocSingleReleasePool : public Pool
 {
   public:
        MultiAllocSingleReleasePool (std::string name, unsigned long item_size, unsigned long nitems);
@@ -68,7 +74,67 @@ class MultiAllocSingleReleasePool : public Pool
        virtual void release (void *);
 
   private:
-    Glib::Mutex* m_lock;
+        Glib::Threads::Mutex m_lock;
+};
+
+class LIBPBD_API 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 LIBPBD_API CrossThreadPool : public Pool
+{
+  public:
+       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 LIBPBD_API PerThreadPool
+{
+  public:
+       PerThreadPool ();
+
+        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:
+        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__