add export visibility control to libpbd (works thus far on linux/gcc)
[ardour.git] / libs / pbd / pbd / pool.h
1 /*
2     Copyright (C) 1998-99 Paul Barton-Davis
3  
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __qm_pool_h__
21 #define __qm_pool_h__
22
23 #include <vector>
24 #include <string>
25
26 #include <glibmm/threads.h>
27
28 #include "pbd/libpbd_visibility.h"
29 #include "pbd/ringbuffer.h"
30
31 /** A pool of data items that can be allocated, read from and written to
32  *  without system memory allocation or locking.
33  */
34 class LIBPBD_API Pool 
35 {
36   public:
37         Pool (std::string name, unsigned long item_size, unsigned long nitems);
38         virtual ~Pool ();
39
40         virtual void *alloc ();
41         virtual void release (void *);
42         
43         std::string name() const { return _name; }
44
45   protected:
46         RingBuffer<void*> free_list; ///< a list of pointers to free items within block
47         std::string _name;
48
49   private:
50         void *block; ///< data storage area
51 };
52
53 class LIBPBD_API SingleAllocMultiReleasePool : public Pool
54 {
55   public:
56         SingleAllocMultiReleasePool (std::string name, unsigned long item_size, unsigned long nitems);
57         ~SingleAllocMultiReleasePool ();
58
59         virtual void *alloc ();
60         virtual void release (void *);
61
62   private:
63         Glib::Threads::Mutex m_lock;
64 };
65
66
67 class LIBPBD_API MultiAllocSingleReleasePool : public Pool
68 {
69   public:
70         MultiAllocSingleReleasePool (std::string name, unsigned long item_size, unsigned long nitems);
71         ~MultiAllocSingleReleasePool ();
72
73         virtual void *alloc ();
74         virtual void release (void *);
75
76   private:
77         Glib::Threads::Mutex m_lock;
78 };
79
80 class LIBPBD_API PerThreadPool;
81
82 /** Management of a per-thread pool of data that is allocated by one thread and
83  *  freed by one other thread. Not safe for use when there is more than 1
84  *  reader and 1 writer. 
85  *
86  *  This is basically a wrapper around a thread-local storage instance of a 
87  *  ringbuffer, made safe for use in the case where multiple threads allocate
88  *  from the ringbuffer and a single thread "frees" the allocations.
89  * 
90  *  Rather than using locks, each thread has its own ringbuffer (and associated
91  *  data), and so it calls alloc(), passes a pointer to the result of the alloc
92  *  to another thread, which later calls push() to "free" it. 
93  */
94 class LIBPBD_API CrossThreadPool : public Pool
95 {
96   public:
97         CrossThreadPool (std::string n, unsigned long isize, unsigned long nitems, PerThreadPool *);
98
99         void* alloc ();
100         void push (void *);
101
102         PerThreadPool* parent () const {
103                 return _parent;
104         }
105
106         bool empty ();
107         
108   private:
109         RingBuffer<void*> pending;
110         PerThreadPool* _parent;
111 };
112
113 /** A class to manage per-thread pools of memory.  One object of this class is instantiated,
114  *  and then it is used to create per-thread pools for 1 or more threads as required.
115  */
116 class LIBPBD_API PerThreadPool
117 {
118   public:
119         PerThreadPool ();
120
121         const Glib::Threads::Private<CrossThreadPool>& key() const { return _key; }
122
123         void  create_per_thread_pool (std::string name, unsigned long item_size, unsigned long nitems);
124         CrossThreadPool* per_thread_pool ();
125
126         void set_trash (RingBuffer<CrossThreadPool*>* t);
127         void add_to_trash (CrossThreadPool *);
128
129   private:
130         Glib::Threads::Private<CrossThreadPool> _key;
131         std::string _name;
132         unsigned long _item_size;
133         unsigned long _nitems;
134
135         /** mutex to protect either changes to the _trash variable, or writes to the RingBuffer */
136         Glib::Threads::Mutex _trash_mutex;
137         RingBuffer<CrossThreadPool*>* _trash;
138 };
139
140 #endif // __qm_pool_h__