summaryrefslogtreecommitdiff
path: root/libs/pbd/pool.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-12-04 19:24:09 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-12-04 19:24:09 +0000
commit4a3d7877f6b03fac7755f997b945583ba5732d13 (patch)
tree1099df5854224acbb17a650215d7f07710b8babe /libs/pbd/pool.cc
parent478fd92039443743babec98812f10921209f1e5a (diff)
cross-thread handling of SessionEvent allocation/deallocation, with widespread consequences
git-svn-id: svn://localhost/ardour2/branches/3.0@6283 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd/pool.cc')
-rw-r--r--libs/pbd/pool.cc72
1 files changed, 66 insertions, 6 deletions
diff --git a/libs/pbd/pool.cc b/libs/pbd/pool.cc
index 2a9022542a..af57871da9 100644
--- a/libs/pbd/pool.cc
+++ b/libs/pbd/pool.cc
@@ -30,11 +30,11 @@ using namespace std;
using namespace PBD;
Pool::Pool (string n, unsigned long item_size, unsigned long nitems)
+ : free_list (nitems)
+ , _name (n)
{
_name = n;
- free_list = new RingBuffer<void*> (nitems);
-
/* since some overloaded ::operator new() might use this,
its important that we use a "lower level" allocator to
get more space.
@@ -48,8 +48,7 @@ Pool::Pool (string n, unsigned long item_size, unsigned long nitems)
ptrlist[i] = static_cast<void *> (static_cast<char*>(block) + (i * item_size));
}
- free_list->write (ptrlist, nitems);
-
+ free_list.write (ptrlist, nitems);
free (ptrlist);
}
@@ -65,7 +64,7 @@ Pool::alloc ()
// cerr << _name << " pool " << " alloc, thread = " << pthread_name() << " space = " << free_list->read_space() << endl;
- if (free_list->read (&ptr, 1) < 1) {
+ if (free_list.read (&ptr, 1) < 1) {
fatal << "CRITICAL: " << _name << " POOL OUT OF MEMORY - RECOMPILE WITH LARGER SIZE!!" << endmsg;
/*NOTREACHED*/
return 0;
@@ -77,7 +76,7 @@ Pool::alloc ()
void
Pool::release (void *ptr)
{
- free_list->write (&ptr, 1);
+ free_list.write (&ptr, 1);
// cerr << _name << ": release, now has " << free_list->read_space() << endl;
}
@@ -144,3 +143,64 @@ SingleAllocMultiReleasePool::release (void* ptr)
Pool::release (ptr);
}
+/*-------------------------------------------------------*/
+
+static void
+free_per_thread_pool (void* ptr)
+{
+ cerr << "Deleting a per thread pool @ " << ptr << endl;
+ Pool* pptr = static_cast<Pool*>(ptr);
+ delete pptr;
+}
+
+PerThreadPool::PerThreadPool ()
+{
+ {
+ /* for some reason this appears necessary to get glib's thread private stuff to work */
+ GPrivate* key;
+ key = g_private_new (NULL);
+ }
+
+ _key = g_private_new (free_per_thread_pool);
+}
+
+void
+PerThreadPool::create_per_thread_pool (string n, unsigned long isize, unsigned long nitems)
+{
+ Pool* p = new CrossThreadPool (n, isize, nitems);
+ g_private_set (_key, p);
+}
+
+CrossThreadPool*
+PerThreadPool::per_thread_pool ()
+{
+ CrossThreadPool* p = static_cast<CrossThreadPool*> (g_private_get (_key));
+ if (!p) {
+ fatal << "programming error: no per-thread pool \"" << _name << "\" for thread " << pthread_self() << endmsg;
+ /*NOTREACHED*/
+ }
+ return p;
+}
+
+CrossThreadPool::CrossThreadPool (string n, unsigned long isize, unsigned long nitems)
+ : Pool (n, isize, nitems)
+ , pending (nitems)
+{
+
+}
+
+void*
+CrossThreadPool::alloc ()
+{
+ void* ptr;
+ while (pending.read (&ptr, 1) == 1) {
+ free_list.write (&ptr, 1);
+ }
+ return Pool::alloc ();
+}
+
+void
+CrossThreadPool::push (void* t)
+{
+ pending.write (&t, 1);
+}