Use test utility function to find evoral test files
[ardour.git] / libs / pbd / pbd / pool.h
index 2d6111a4a35d69594a7254d1b1bedb8a51ef97e0..a28325cebf75737de37ae7cae1a89e729539f918 100644 (file)
 #include <vector>
 #include <string>
 
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
 
+#include "pbd/libpbd_visibility.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 
+class LIBPBD_API Pool 
 {
   public:
        Pool (std::string name, unsigned long item_size, unsigned long nitems);
@@ -49,7 +50,7 @@ class Pool
        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);
@@ -59,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);
@@ -73,13 +74,24 @@ class MultiAllocSingleReleasePool : public Pool
        virtual void release (void *);
 
   private:
-    Glib::Mutex* m_lock;
+        Glib::Threads::Mutex m_lock;
 };
 
-class PerThreadPool;
-
-/** A per-thread pool of data */
-class CrossThreadPool : public Pool
+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 *);
@@ -99,31 +111,28 @@ class CrossThreadPool : public Pool
 };
 
 /** 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 as required.
+ *  and then it is used to create per-thread pools for 1 or more threads as required.
  */
-class PerThreadPool
+class LIBPBD_API 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) {
-               _trash = t;
-       }
-
+       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;
-       Glib::Mutex _trash_write_mutex;
 };
 
 #endif // __qm_pool_h__