#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);
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);
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);
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 *);
};
/** 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__