advance compilation to include plugin_ui.cc
[ardour.git] / libs / glibmm2 / glibmm / threadpool.cc
1 // -*- c++ -*-
2 /* $Id$ */
3
4 /* Copyright (C) 2002 The gtkmm Development Team
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include <glibmm/threadpool.h>
22 #include <glibmm/exceptionhandler.h>
23 #include <glib.h>
24 #include <list>
25 #include <glibmmconfig.h>
26
27 GLIBMM_USING_STD(list)
28
29
30 namespace Glib
31 {
32
33 // internal
34 class ThreadPool::SlotList
35 {
36 public:
37   SlotList();
38   ~SlotList();
39
40   sigc::slot<void>* push(const sigc::slot<void>& slot);
41   sigc::slot<void>  pop(sigc::slot<void>* slot_ptr);
42
43   void lock_and_unlock();
44
45 private:
46   Glib::Mutex                     mutex_;
47   std::list< sigc::slot<void> >  list_;
48
49   // noncopyable
50   SlotList(const ThreadPool::SlotList&);
51   ThreadPool::SlotList& operator=(const ThreadPool::SlotList&);
52 };
53
54 ThreadPool::SlotList::SlotList()
55 {}
56
57 ThreadPool::SlotList::~SlotList()
58 {}
59
60 sigc::slot<void>* ThreadPool::SlotList::push(const sigc::slot<void>& slot)
61 {
62   Mutex::Lock lock (mutex_);
63
64   list_.push_back(slot);
65   return &list_.back();
66 }
67
68 sigc::slot<void> ThreadPool::SlotList::pop(sigc::slot<void>* slot_ptr)
69 {
70   sigc::slot<void> slot;
71
72   {
73     Mutex::Lock lock (mutex_);
74
75     std::list< sigc::slot<void> >::iterator pslot = list_.begin();
76     while(pslot != list_.end() && slot_ptr != &*pslot)
77       ++pslot;
78
79     if(pslot != list_.end())
80     {
81       slot = *pslot;
82       list_.erase(pslot);
83     }
84   }
85
86   return slot;
87 }
88
89 void ThreadPool::SlotList::lock_and_unlock()
90 {
91   mutex_.lock();
92   mutex_.unlock();
93 }
94
95 } // namespace Glib
96
97
98 namespace
99 {
100
101 static void call_thread_entry_slot(void* data, void* user_data)
102 {
103   try
104   {
105     Glib::ThreadPool::SlotList *const slot_list =
106         static_cast<Glib::ThreadPool::SlotList*>(user_data);
107
108     sigc::slot<void> slot (slot_list->pop(static_cast<sigc::slot<void>*>(data)));
109
110     slot();
111   }
112   catch(Glib::Thread::Exit&)
113   {
114     // Just exit from the thread.  The Thread::Exit exception
115     // is our sane C++ replacement of g_thread_exit().
116   }
117   catch(...)
118   {
119     Glib::exception_handlers_invoke();
120   }
121 }
122
123 } // anonymous namespace
124
125
126 namespace Glib
127 {
128
129 ThreadPool::ThreadPool(int max_threads, bool exclusive)
130 :
131   gobject_   (0),
132   slot_list_ (new SlotList())
133 {
134   GError* error = 0;
135
136   gobject_ = g_thread_pool_new(
137       &call_thread_entry_slot, slot_list_, max_threads, exclusive, &error);
138
139   if(error)
140   {
141     delete slot_list_;
142     slot_list_ = 0;
143     Glib::Error::throw_exception(error);
144   }
145 }
146
147 ThreadPool::~ThreadPool()
148 {
149   if(gobject_)
150     g_thread_pool_free(gobject_, 1, 1);
151
152   if(slot_list_)
153   {
154     slot_list_->lock_and_unlock();
155     delete slot_list_;
156   }
157 }
158
159 void ThreadPool::push(const sigc::slot<void>& slot)
160 {
161   sigc::slot<void> *const slot_ptr = slot_list_->push(slot);
162
163   GError* error = 0;
164   g_thread_pool_push(gobject_, slot_ptr, &error);
165
166   if(error)
167   {
168     slot_list_->pop(slot_ptr);
169     Glib::Error::throw_exception(error);
170   }
171 }
172
173 void ThreadPool::set_max_threads(int max_threads)
174 {
175   GError* error = 0;
176   g_thread_pool_set_max_threads(gobject_, max_threads, &error);
177
178   if(error)
179     Glib::Error::throw_exception(error);
180 }
181
182 int ThreadPool::get_max_threads() const
183 {
184   return g_thread_pool_get_max_threads(gobject_);
185 }
186
187 unsigned int ThreadPool::get_num_threads() const
188 {
189   return g_thread_pool_get_num_threads(gobject_);
190 }
191
192 unsigned int ThreadPool::unprocessed() const
193 {
194   return g_thread_pool_unprocessed(gobject_);
195 }
196
197 bool ThreadPool::get_exclusive() const
198 {
199   g_return_val_if_fail(gobject_ != 0, false);
200
201   return gobject_->exclusive;
202 }
203
204 void ThreadPool::shutdown(bool immediately)
205 {
206   if(gobject_)
207   {
208     g_thread_pool_free(gobject_, immediately, 1);
209     gobject_ = 0;
210   }
211
212   if(slot_list_)
213   {
214     slot_list_->lock_and_unlock();
215     delete slot_list_;
216     slot_list_ = 0;
217   }
218 }
219
220 // static
221 void ThreadPool::set_max_unused_threads(int max_threads)
222 {
223   g_thread_pool_set_max_unused_threads(max_threads);
224 }
225
226 // static
227 int ThreadPool::get_max_unused_threads()
228 {
229   return g_thread_pool_get_max_unused_threads();
230 }
231
232 // static
233 unsigned int ThreadPool::get_num_unused_threads()
234 {
235   return g_thread_pool_get_num_unused_threads();
236 }
237
238 // static
239 void ThreadPool::stop_unused_threads()
240 {
241   g_thread_pool_stop_unused_threads();
242 }
243
244 } // namespace Glib
245