1 #ifndef _GLIBMM_THREADPOOL_H
2 #define _GLIBMM_THREADPOOL_H
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 Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 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  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <glibmmconfig.h>
21 
22 #ifndef GLIBMM_DISABLE_DEPRECATED
23 
24 #include <sigc++/sigc++.h>
25 
26 extern "C" {
27 using GThreadPool = struct _GThreadPool;
28 }
29 
30 namespace Glib
31 {
32 
33 /** @defgroup ThreadPools Thread Pools
34  * Pools of threads to execute work concurrently.
35  *
36  * @deprecated This is deprecated in favor of the standard C++ concurrency API in C++11 and C++14.
37  *
38  * @{
39  */
40 
41 // TODO: Is std::async() an appropriate replacement to mention for this deprecated API?
42 
43 /** A pool of threads to execute work concurrently.
44  *
45  * @deprecated This is deprecated in favor of the standard C++ concurrency API in C++11 and C++14.
46  */
47 class GLIBMM_API ThreadPool
48 {
49 public:
50   /** Constructs a new thread pool.
51    * Whenever you call ThreadPool::push(), either a new thread is created or an
52    * unused one is reused. At most @a max_threads threads are running
53    * concurrently for this thread pool. @a max_threads&nbsp;=&nbsp;-1 allows
54    * unlimited threads to be created for this thread pool.
55    *
56    * The parameter @a exclusive determines, whether the thread pool owns all
57    * threads exclusive or whether the threads are shared globally. If @a
58    * exclusive is <tt>true</tt>, @a max_threads threads are started immediately
59    * and they will run exclusively for this thread pool until it is destroyed
60    * by ~ThreadPool(). If @a exclusive is <tt>false</tt>, threads are created
61    * when needed and shared between all non-exclusive thread pools.  This
62    * implies that @a max_threads may not be -1 for exclusive thread pools.
63    *
64    * @param max_threads The maximal number of threads to execute concurrently
65    * in the new thread pool, -1 means no limit.
66    * @param exclusive Should this thread pool be exclusive?
67    * @throw Glib::ThreadError An error can only occur when @a exclusive is
68    * set to <tt>true</tt> and not all @a max_threads threads could be created.
69    */
70   explicit ThreadPool(int max_threads = -1, bool exclusive = false);
71   virtual ~ThreadPool() noexcept;
72 
73   // See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
74   // TODO: At the next ABI break, consider changing const sigc::slot<void>& slot
75   // to const std::function<void()>& func, if it can be assumed that all supported
76   // compilers understand the C++11 template class std::function<>.
77   /** Inserts @a slot into the list of tasks to be executed by the pool.
78    * When the number of currently running threads is lower than the maximal
79    * allowed number of threads, a new thread is started (or reused).  Otherwise
80    * @a slot stays in the queue until a thread in this pool finishes its
81    * previous task and processes @a slot.
82    *
83    * Because sigc::trackable is not thread-safe, if the slot represents a
84    * non-static class method and is created by sigc::mem_fun(), the class concerned
85    * should not derive from sigc::trackable. You can use, say, boost::bind() or,
86    * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun().
87    *
88    * @param slot A new task for the thread pool.
89    * @throw Glib::ThreadError An error can only occur when a new thread
90    * couldn't be created. In that case @a slot is simply appended to the
91    * queue of work to do.
92    */
93   void push(const sigc::slot<void>& slot);
94 
95   /** Sets the maximal allowed number of threads for the pool.
96    * A value of -1 means that the maximal number of threads is unlimited.
97    * Setting @a max_threads to 0 means stopping all work for pool. It is
98    * effectively frozen until @a max_threads is set to a non-zero value again.
99    *
100    * A thread is never terminated while it is still running. Instead the
101    * maximal number of threads only has effect for the allocation of new
102    * threads in ThreadPool::push().  A new thread is allocated whenever the
103    * number of currently running threads in the pool is smaller than the
104    * maximal number.
105    *
106    * @param max_threads A new maximal number of threads for the pool.
107    * @throw Glib::ThreadError An error can only occur when a new thread
108    * couldn't be created.
109    */
110   void set_max_threads(int max_threads);
111 
112   /** Returns the maximal number of threads for the pool.
113    * @return The maximal number of threads.
114    */
115   int get_max_threads() const;
116 
117   /** Returns the number of threads currently running in the pool.
118    * @return The number of threads currently running.
119    */
120   unsigned int get_num_threads() const;
121 
122   /** Returns the number of tasks still unprocessed in the pool.
123    * @return The number of unprocessed tasks.
124    */
125   unsigned int unprocessed() const;
126 
127   /** Returns whether all threads are exclusive to this pool.
128    * @return Whether all threads are exclusive to this pool.
129    */
130   bool get_exclusive() const;
131 
132   /** Frees all resources allocated for the pool.
133    * If @a immediately is <tt>true</tt>, no new task is processed.  Otherwise the
134    * pool is not freed before the last task is processed.  Note however, that no
135    * thread of this pool is interrupted while processing a task. Instead at least
136    * all still running threads can finish their tasks before the pool is freed.
137    *
138    * This method does not return before all tasks to be processed (dependent on
139    * @a immediately, whether all or only the currently running) are ready.
140    * After calling shutdown() the pool must not be used anymore.
141    *
142    * @param immediately Should the pool shut down immediately?
143    */
144   void shutdown(bool immediately = false);
145 
146   /** Sets the maximal number of unused threads to @a max_threads.
147    * If @a max_threads is -1, no limit is imposed on the number of unused threads.
148    * @param max_threads Maximal number of unused threads.
149    */
150   static void set_max_unused_threads(int max_threads);
151 
152   /** Returns the maximal allowed number of unused threads.
153    * @return The maximal number of unused threads.
154    */
155   static int get_max_unused_threads();
156 
157   /** Returns the number of currently unused threads.
158    * @return The number of currently unused threads.
159    */
160   static unsigned int get_num_unused_threads();
161 
162   /** Stops all currently unused threads.
163    * This does not change the maximal number of unused threads.  This function can
164    * be used to regularly stop all unused threads e.g. from Glib::signal_timeout().
165    */
166   static void stop_unused_threads();
167 
gobj()168   GThreadPool* gobj() { return gobject_; }
gobj()169   const GThreadPool* gobj() const { return gobject_; }
170 
171 #ifndef DOXYGEN_SHOULD_SKIP_THIS
172   class SlotList;
173 #endif
174 
175 private:
176   GThreadPool* gobject_;
177   SlotList* slot_list_;
178 
179   ThreadPool(const ThreadPool&);
180   ThreadPool& operator=(const ThreadPool&);
181 };
182 
183 /** @} group ThreadPools */
184 
185 /***************************************************************************/
186 /*  inline implementation                                                  */
187 /***************************************************************************/
188 
189 #ifndef DOXYGEN_SHOULD_SKIP_THIS
190 
191 /**** Glib::Private ********************************************************/
192 
193 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
194 
195 } // namespace Glib
196 
197 #endif // GLIBMM_DISABLE_DEPRECATED
198 
199 #endif /* _GLIBMM_THREADPOOL_H */
200