c++-gtk-utils
|
00001 /* Copyright (C) 2005 to 2012 Chris Vine 00002 00003 The library comprised in this file or of which this file is part is 00004 distributed by Chris Vine under the GNU Lesser General Public 00005 License as follows: 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Lesser General Public License 00009 as published by the Free Software Foundation; either version 2.1 of 00010 the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, but 00013 WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Lesser General Public License, version 2.1, for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public 00018 License, version 2.1, along with this library (see the file LGPL.TXT 00019 which came with this source code package in the c++-gtk-utils 00020 sub-directory); if not, write to the Free Software Foundation, Inc., 00021 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00022 00023 */ 00024 00025 #ifndef CGU_THREAD_H 00026 #define CGU_THREAD_H 00027 00028 #include <memory> // for std::unique_ptr or std::auto_ptr 00029 #include <utility> // for std::move 00030 00031 #include <pthread.h> 00032 00033 #include <c++-gtk-utils/callback.h> 00034 #include <c++-gtk-utils/mutex.h> 00035 #include <c++-gtk-utils/cgu_config.h> 00036 00037 namespace Cgu { 00038 00039 namespace Thread { 00040 00041 /** 00042 * @class Cgu::Thread::Thread thread.h c++-gtk-utils/thread.h 00043 * @brief A class representing a pthread thread. 00044 * @sa Thread::Mutex Thread::Mutex::Lock Thread::Cond Thread::Future Thread::JoinableHandle 00045 * 00046 * The Thread class encapsulates a pthread thread. It can start, join 00047 * and cancel a thread. 00048 * 00049 * The Thread class, and the associated CancelBlock class, can be used 00050 * interchangeably with (and mixed with) GThread objects and 00051 * functions, and GMutex, GStaticMutex, GStaticRecMutex and GCond, as 00052 * they all use pthreads underneath on POSIX and other unix-like OSes. 00053 * In addition it can be used with threads started with the C++11 00054 * threading facilities, as in C++11 on unix-like OSes these 00055 * facilities will be built on top of pthreads (for which purpose 00056 * C++11 provides the std::native_handle_type type and 00057 * std::thread::native_handle() function). Even where they are not, 00058 * they will use the same threading primitives provided by the kernel. 00059 * 00060 * @anchor ThreadsAnchor 00061 * @b c++-gtk-utils @b library @b and @b C++11 @b threads 00062 * 00063 * As mentioned above, the thread facilities provided by this library 00064 * can be freely interchanged with the threading facilities provided 00065 * by C++11. 00066 * 00067 * The main features available from this library and not C++11 are 00068 * thread cancellation and the associated Cgu::Thread::CancelBlock 00069 * class, and the Cgu::Thread::JoinableHandle class for scoped 00070 * joinable thread handling. 00071 * 00072 * C++11 does not provide thread cancellation or interruption support, 00073 * and C++ will never be able to do so on a complete basis because to 00074 * do so requires support from the underlying OS, which therefore 00075 * makes it platform specific (in this case, POSIX specific): 00076 * cancellation is only of limited use if it cannot reliably interrupt 00077 * blocking system calls. The POSIX specification sets out the 00078 * interruptible cancellation points in System Interfaces, section 00079 * 2.9.5, Cancellation Points, and in effect specifies all the system 00080 * calls which can block as cancellation points. 00081 * 00082 * Whether, in C++ programs, destructors of local objects in the 00083 * cancelled thread are called is also system specific and is not 00084 * specified by POSIX. Most modern commercial unixes, and recent 00085 * linux/BSD distributions based on NPTL (in the case of Linux, those 00086 * based on 2.6/3.* kernels), will unwind the stack and call 00087 * destructors on thread cancellation by means of a pseudo-exception, 00088 * but older distributions relying on the former linuxthreads 00089 * implementation will not. Therefore for maximum portability 00090 * cancellation would only be used where there are plain data 00091 * structures/built-in types in existence in local scope when it 00092 * occurs, and if there is anything in free store to be released some 00093 * clean-ups would be implemented with 00094 * pthread_cleanup_push()/pthread_cleanup_pop(). This should be 00095 * controlled with pthread_setcancelstate() and/or the CancelBlock 00096 * class to choose the cancellation point. 00097 * 00098 * One of the (perhaps odd) features of C++11 threads is that if the 00099 * destructor of a std::thread object is called which represents a 00100 * joinable thread which has not been detach()ed or join()ed, the 00101 * whole program is terminated with a call to std::terminate(), which 00102 * makes it difficult to use in the presence of exceptions. Often 00103 * what is wanted however is for join() to be called on a joinable 00104 * thread where the associated thread object goes out of scope, or 00105 * (provided it is done carefully and knowingly) for detach() to be 00106 * called. The Cgu::Thread::JoinableHandle class can be used where 00107 * either of these two is the appropriate response to this situation. 00108 * 00109 * In addition, the c++-gtk-utils library provides the following which 00110 * are not present in C++11: a guaranteed monotonic clock on timed 00111 * condition variable waits where the operating system supports them; 00112 * read-write locks; and a Cgu::Thread::Future object which is more 00113 * intuitive to use than C++11 futures and features a built in 00114 * Cgu::SafeEmitter object which emits when the particular task has 00115 * completed, and (since version 2.0.2) has associated 00116 * Cgu::Thread::Future::when() methods for passing the result to a 00117 * glib main loop. 00118 * 00119 * @b c++-gtk-utils @b library @b and @b gthreads 00120 * 00121 * As mentioned above, the thread facilities provided by this library 00122 * can be freely interchanged with the threading facilities provided 00123 * by glib. 00124 * 00125 * The main features available with this thread implementation and not 00126 * GThreads are thread cancellation, the mutex scoped locking classes 00127 * Cgu::Thread::Mutex::Lock and Cgu::Thread::RecMutex::Lock, the 00128 * joinable thread scoped management class Cgu::Thread::JoinableHandle 00129 * and the Cgu::Thread::Future class (abstracting thread functions 00130 * which provide a result). 00131 * 00132 * There is no need from the perspective of this class to call 00133 * g_thread_init() before Cgu::Thread::Thread::start() is called, but 00134 * but prior to glib version 2.32 glib itself is not thread-safe 00135 * without g_thread_init(), so where this class is used with glib < 00136 * 2.32, g_thread_init() should be called at program initialization. 00137 * 00138 * See @ref Threading for particulars about GTK+ thread safety. 00139 */ 00140 00141 00142 class Thread { 00143 pthread_t thread; 00144 // private constructor - this class can only be created with Thread::start 00145 Thread() {} 00146 public: 00147 /** 00148 * This class cannot be copied: it is intended to be held by 00149 * std::unique_ptr. The copy constructor is deleted. 00150 */ 00151 Thread(const Thread&) = delete; 00152 00153 /** 00154 * This class cannot be copied: it is intended to be held by 00155 * std::unique_ptr. The assignment operator is deleted. 00156 */ 00157 Thread& operator=(const Thread&) = delete; 00158 00159 /** 00160 * Cancels the thread represented by this Thread object. It can be 00161 * called by any thread. The effect is undefined if the thread 00162 * represented by this Thread object has both (a) already terminated 00163 * and (b) been detached or had a call to join() made for it. 00164 * Accordingly, if the user is not able to establish from the program 00165 * logic whether the thread has terminated, the thread must be created 00166 * as joinable and cancel() must not be called after a call to 00167 * detach() has been made or a call to join() has returned. A 00168 * Thread::JoinableHandle object can used to ensure this. It does not 00169 * throw. 00170 * @note Use this method with care - sometimes its use is unavoidable 00171 * but destructors for local objects may not be called if a thread 00172 * exits by virtue of a call to cancel() (that depends on the 00173 * implementation). Most modern commercial unixes, and recent 00174 * linux/BSD distributions based on NPTL, will unwind the stack and 00175 * call destructors on thread cancellation by means of a 00176 * pseudo-exception, but older distributions relying on the former 00177 * linuxthreads implementation will not. Therefore for maximum 00178 * portability only have plain data structures/built-in types in 00179 * existence in local scope when it occurs and if there is anything in 00180 * free store to be released implement some clean-ups with 00181 * pthread_cleanup_push()/pthread_cleanup_pop(). This should be 00182 * controlled with pthread_setcancelstate() and/or the CancelBlock 00183 * class to choose the cancellation point. 00184 * @sa Cgu::Thread::Exit 00185 */ 00186 void cancel() {pthread_cancel(thread);} 00187 00188 /** 00189 * Joins the thread represented by this Thread object (that is, waits 00190 * for it to terminate). It can be called by any thread other than 00191 * the one represented by this Thread object. The result is undefined 00192 * if the thread is or was detached or join() has already been called 00193 * for the thread (a Thread::JoinableHandle object will however give a 00194 * defined result in such cases for threads originally started as 00195 * joinable). It does not throw. 00196 */ 00197 void join() {pthread_join(thread, 0);} 00198 00199 /** 00200 * Detaches the thread represented by this Thread object where it is 00201 * joinable, so as to make it unjoinable. The effect is unspecified 00202 * if the thread is already unjoinable (a Thread::JoinableHandle 00203 * object will however give a defined result in such cases for threads 00204 * originally started as joinable). It does not throw. 00205 */ 00206 void detach() {pthread_detach(thread);} 00207 00208 /** 00209 * Specifies whether the calling thread is the same thread as is 00210 * represented by this Thread object. The effect is undefined if the 00211 * thread represented by this Thread object has both (a) already 00212 * terminated and (b) been detached or had a call to join() made for 00213 * it. Accordingly, if the user is not able to establish from the 00214 * program logic whether the thread has terminated, the thread must be 00215 * created as joinable and is_caller() must not be called after a call 00216 * to detach() has been made or a call to join() has returned. A 00217 * Thread::JoinableHandle object can used to ensure this. This method 00218 * does not throw. 00219 * @return Returns true if the caller is in the thread represented by 00220 * this Thread object. 00221 */ 00222 bool is_caller() {return pthread_equal(thread, pthread_self());} 00223 00224 /** 00225 * Starts a new thread. It can be called by any thread. 00226 * @param cb A callback object (created by Callback::make()) 00227 * encapsulating the function to be executed by the new thread. The 00228 * Thread object returned by this function will take ownership of the 00229 * callback: it will automatically be deleted either by the new thread 00230 * when it has finished with it, or by this method in the calling 00231 * thread if the attempt to start a new thread fails (including if 00232 * std::bad_alloc is thrown). 00233 * @param joinable Whether the join() method may be called in relation 00234 * to the new thread. 00235 * @return A Thread object representing the new thread which has been 00236 * started, held by a std::unique_ptr object as it has single 00237 * ownership semantics. The std::unique_ptr object will be empty 00238 * (that is std::unique_ptr<Cgu::Thread::Thread>::get() will return 0) 00239 * if the thread did not start correctly, which would mean that memory 00240 * is exhausted, the pthread thread limit has been reached or pthread 00241 * has run out of other resources to start new threads. 00242 * @exception std::bad_alloc This method might throw std::bad_alloc if 00243 * memory is exhausted and the system throws in that case. (This 00244 * exception will not be thrown if the library has been installed 00245 * using the --with-glib-memory-slices-no-compat configuration option: 00246 * instead glib will terminate the program if it is unable to obtain 00247 * memory from the operating system.) 00248 * @note 1. The thread will keep running even if the return value of 00249 * start() goes out of scope (but it will no longer be possible to 00250 * call any of the methods in this class for it, which is fine if the 00251 * thread is not started as joinable and it is not intended to cancel 00252 * it). 00253 * @note 2. If the thread is started with the joinable attribute, the 00254 * user must subsequently either call the join() or the detach() 00255 * method, as otherwise a resource leak may occur (the destructor of 00256 * this class does not call detach() automatically). Alternatively, 00257 * the return value of this method can be passed to a 00258 * Thread::JoinableHandle object which will do this automatically in 00259 * the Thread::JoinableHandle object's destructor. 00260 * @note 3. Any Thread::Exit exception thrown from the function 00261 * executed by the new thread will be caught and consumed. The thread 00262 * will safely terminate and unwind the stack in so doing. 00263 * @note 4. If any uncaught exception other than Thread::Exit is 00264 * allowed to propagate from the initial function executed by the new 00265 * thread, the exception is not consumed (NPTL's forced stack 00266 * unwinding on cancellation does not permit catching with an ellipsis 00267 * argument without rethrowing, and even if it did permit it, the 00268 * result would be an unreported error). The C++11 standard requires 00269 * std::terminate() to be called in such a case and so the entire 00270 * program terminated. Accordingly, a user must make sure that no 00271 * exceptions, other than Thread::Exit or any cancellation 00272 * pseudo-exception, can propagate from the initial function executed 00273 * by the new thread. 00274 * @note 5. If the library is compiled using the --with-auto-ptr 00275 * configuration option, then this function will return a 00276 * Thread::Thread object by std::auto_ptr instead of std::unique_ptr 00277 * in order to retain compatibility with the 1.2 series of the 00278 * library. 00279 */ 00280 #ifdef CGU_USE_AUTO_PTR 00281 static std::auto_ptr<Cgu::Thread::Thread> start(const Cgu::Callback::Callback* cb, 00282 bool joinable); 00283 #else 00284 static std::unique_ptr<Cgu::Thread::Thread> start(const Cgu::Callback::Callback* cb, 00285 bool joinable); 00286 #endif 00287 00288 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT 00289 CGU_GLIB_MEMORY_SLICES_FUNCS 00290 #endif 00291 }; 00292 00293 /** 00294 * @class Cgu::Thread::JoinableHandle thread.h c++-gtk-utils/thread.h 00295 * @brief A class wrapping a Thread::Thread object representing a 00296 * joinable thread. 00297 * @sa Thread::Thread Thread::Future 00298 * 00299 * This class enables a joinable thread to be made more easily 00300 * exception safe. It can also be used to provide that a joinable 00301 * thread is not detached or joined while other methods dependent on 00302 * that might still be called, and to provide a defined result where 00303 * there are multiple calls to join() and/or detach(). When it is 00304 * destroyed, it will either detach or join the thread represented by 00305 * the wrapped Thread::Thread object unless it has previously been 00306 * detached or joined using the detach() or join() methods, so 00307 * avoiding thread resource leaks. Whether it will detach() or join() 00308 * on destruction depends on the Thread::JoinableHandle::Action 00309 * argument passed to the 00310 * Thread::JoinableHandle::JoinableHandle(std::unique_ptr<Thread::Thread>, 00311 * Action) constructor. 00312 * 00313 * Passing Thread::JoinableHandle::detach_on_exit to that argument is 00314 * not always the correct choice where the thread callback has been 00315 * bound to a reference argument in local scope and an exception might 00316 * be thrown, because the thread will keep running after the 00317 * Thread::JoinableHandle object and other local variables have 00318 * (because of the exception) gone out of scope. Consider the 00319 * following trivial parallelized calculation example: 00320 * 00321 * @code 00322 * std::vector<int> get_readings(); 00323 * void get_mean(const std::vector<int>& v, int& result); 00324 * void get_std_deviation(const std::vector<int>& v, int& result); // might throw 00325 * void show_result(int mean, int deviation); 00326 * 00327 * using namespace Cgu; 00328 * void do_calc() { 00329 * int i, j; 00330 * std::vector<int> v = get_readings(); 00331 * // with bound reference arguments, Callback::make() requires explicit type instantation 00332 * std::unique_ptr<Thread::Thread> t = 00333 * Thread::Thread::start(Callback::make<const std::vector<int>&, int&>(&get_mean, v, i), true); 00334 * if (t.get()) { // checks whether thread started correctly 00335 * get_std_deviation(v, j); 00336 * t->join(); 00337 * show_result(i, j); 00338 * } 00339 * } 00340 * @endcode 00341 * 00342 * If get_std_deviation() throws, as well as there being a potential 00343 * thread resource leak by virtue of no join being made, the thread 00344 * executing get_mean() will continue running and attempt to access 00345 * variable v, and put its result in variable i, which may by then 00346 * both be out of scope. To deal with such a case, the thread could 00347 * be wrapped in a Thread::JoinableHandle object which joins on exit 00348 * rather than detaches, for example: 00349 * 00350 * @code 00351 * ... 00352 * using namespace Cgu; 00353 * void do_calc() { 00354 * int i, j; 00355 * std::vector<int> v = get_readings(); 00356 * // with reference arguments, Callback::make() requires explicit type instantation 00357 * Thread::JoinableHandle t(Thread::Thread::start(Callback::make<const std::vector<int>&, int&>(&get_mean, v, i), true), 00358 * Thread::JoinableHandle::join_on_exit); 00359 * if (t.is_managing()) { // checks whether thread started correctly 00360 * get_std_deviation(v, j); 00361 * t.join(); 00362 * show_result(i, j); 00363 * } 00364 * } 00365 * @endcode 00366 * 00367 * Better still, however, would be to use Cgu::Thread::Future in this 00368 * kind of usage, namely a usage where a worker thread is intended to 00369 * provide a result for inspection. 00370 * 00371 * @note These examples assume that the std::vector library 00372 * implementation permits concurrent reads of a vector object by 00373 * different threads. Whether that is the case depends on the 00374 * documentation of the library concerned (if designed for a 00375 * multi-threaded environment, most will permit this). 00376 */ 00377 class JoinableHandle { 00378 public: 00379 enum Action {detach_on_exit, join_on_exit}; 00380 00381 private: 00382 Mutex mutex; // make this the first member so the constructors are strongly exception safe 00383 Action action; 00384 bool detached; 00385 std::unique_ptr<Cgu::Thread::Thread> thread; 00386 00387 public: 00388 /** 00389 * Cancels the thread represented by the wrapped Thread::Thread 00390 * object. It can be called by any thread. The effect is undefined 00391 * if when called the thread represented by the wrapped Thread::Thread 00392 * object has both (a) already terminated and (b) had a call to join() 00393 * or detach() made for it. Accordingly, if the user is not able to 00394 * establish from the program logic whether the thread has terminated, 00395 * cancel() must not be called after a call to detach() has been made 00396 * or a call to join() has returned: this can be ensured by only 00397 * detaching or joining via this object's destructor (that is, by not 00398 * using the explicit detach() and join() methods). This method does 00399 * not throw. 00400 * @note Use this method with care - see Thread::cancel() for further 00401 * information. 00402 */ 00403 void cancel(); 00404 00405 /** 00406 * Joins the thread represented by the wrapped Thread::Thread object 00407 * (that is, waits for it to terminate), unless the detach() or join() 00408 * method has previously been called in which case this call does 00409 * nothing. It can be called by any thread other than the one 00410 * represented by the wrapped Thread::Thread object, but only one 00411 * thread can wait on it: if one thread (thread A) calls it while 00412 * another thread (thread B) is already blocking on it, thread A's 00413 * call to this method will return immediately and return false. It 00414 * does not throw. 00415 * @return true if a successful join() has been accomplished (that is, 00416 * detach() or join() have not previously been called), otherwise 00417 * false. 00418 */ 00419 bool join(); 00420 00421 /** 00422 * Detaches the thread represented by this Thread::Thread object, so 00423 * as to make it unjoinable, unless the detach() or join() method has 00424 * previously been called in which case this call does nothing. It 00425 * does not throw. 00426 */ 00427 void detach(); 00428 00429 /** 00430 * Specifies whether the calling thread is the same thread as is 00431 * represented by the wrapped Thread::Thread object. It can be called 00432 * by any thread. The effect is undefined if the thread represented 00433 * by the wrapped Thread::Thread object has both (a) already 00434 * terminated and (b) had a call to join() or detach() made for it. 00435 * Accordingly, if the user is not able to establish from the program 00436 * logic whether the thread has terminated, is_caller() must not be 00437 * called after a call to detach() has been made or a call to join() 00438 * has returned: this can be ensured by only detaching or joining via 00439 * this object's destructor (that is, by not using the explicit 00440 * detach() and join() methods). This method does not throw. 00441 * @return Returns true if the caller is in the thread represented by 00442 * the wrapped Thread::Thread object. If not, or this JoinableHandle 00443 * does not wrap any Thread object, then returns false. 00444 */ 00445 bool is_caller(); 00446 00447 /** 00448 * Specifies whether this JoinableHandle object has been initialized 00449 * with a Thread::Thread object representing a correctly started 00450 * thread in respect of which neither JoinableHandle::detach() nor 00451 * JoinableHandle::join() has been called. It can be called by any 00452 * thread. It is principally intended to enable the constructor 00453 * taking a std::unique_ptr<Cgu::Thread::Thread> object to be directly 00454 * initialized by a call to Thread::Thread::start(), by providing a 00455 * means for the thread calling Thread::Thread::start() to check 00456 * afterwards that the new thread did, in fact, start correctly. Note 00457 * that this method will return true even after the thread has 00458 * finished, provided neither the join() nor detach() method has been 00459 * called. 00460 * @return Returns true if this object has been initialized by a 00461 * Thread::Thread object representing a correctly started thread in 00462 * respect of which neither JoinableHandle::detach() nor 00463 * JoinableHandle::join() has been called, otherwise false. 00464 */ 00465 bool is_managing(); 00466 00467 /** 00468 * Moves one JoinableHandle object to another JoinableHandle object. 00469 * This is a move operation which transfers ownership to the assignee, 00470 * as the handles store their Thread::Thread object by 00471 * std::unique_ptr<>. Any existing thread managed by the assignee 00472 * prior to the move will be detached if it has not already been 00473 * detached or joined. This method will not throw. 00474 * @param h The assignor/movant, which will cease to hold a valid 00475 * Thread::Thread object after the move has taken place. 00476 * @return A reference to the assignee JoinableHandle object after 00477 * assignment. 00478 * @note 1. This method is thread safe as regards the assignee (the 00479 * object assigned to), but no synchronization is carried out with 00480 * respect to the rvalue assignor/movant. This is because temporaries 00481 * are only visible and accessible in the thread carrying out the move 00482 * operation and synchronization for them would represent pointless 00483 * overhead. In a case where the user uses std::move to force a move 00484 * from a named object, and that named object's lifetime is managed by 00485 * (or the object is otherwise accessed by) a different thread than 00486 * the one making the move, the user must carry out her own 00487 * synchronization with respect to that different thread, as the named 00488 * object will be mutated by the move. 00489 * @note 2. If the library is compiled using the --with-auto-ptr 00490 * configuration option, then this operator's signature is 00491 * JoinableHandle& operator=(JoinableHandle& h) in order to retain 00492 * compatibility with the 1.2 series of the library. 00493 */ 00494 #ifdef CGU_USE_AUTO_PTR 00495 JoinableHandle& operator=(JoinableHandle& h); 00496 #else 00497 JoinableHandle& operator=(JoinableHandle&& h); 00498 #endif 00499 00500 /** 00501 * This constructor initializes a new JoinableHandle object with a 00502 * std::unique_ptr<Thread::Thread> object, as provided by 00503 * Thread::Thread::start(). This is a move operation which transfers 00504 * ownership to the new object. 00505 * @param thr The initializing Thread::Thread object (which must have 00506 * been created as joinable) passed by a std::unique_ptr smart 00507 * pointer. This is a move operation. 00508 * @param act Either Thread::JoinableHandle::detach_on_exit (which 00509 * will cause the destructor to detach the thread if it has not 00510 * previously been detached or joined) or 00511 * Thread::JoinableHandle::join_on_exit (which will cause the 00512 * destructor to join the thread if it has not previously been 00513 * detached or joined). 00514 * @exception Cgu::Thread::MutexError Throws this exception if 00515 * initialization of the internal mutex fails. The constructor is 00516 * strongly exception safe: if Cgu::Thread::MutexError is thrown, the 00517 * initializing std::unique_ptr<Cgu::Thread::Thread> object will be 00518 * left unchanged. (It is often not worth checking for this 00519 * exception, as it means either memory is exhausted or pthread has 00520 * run out of other resources to create new mutexes.) 00521 * @note 1. It is not necessary to check that the thread parameter 00522 * represents a correctly started thread (that is, that thr.get() does 00523 * not return 0) before this constructor is invoked, because that can 00524 * be done after construction by calling JoinableHandle::is_managing() 00525 * (a JoinableHangle object can safely handle a case where thr.get() 00526 * does return 0). This enables a JoinableHandle object to be 00527 * directly initialized by this constructor from a call to 00528 * Thread::Thread::start(). 00529 * @note 2. No synchronization is carried out with respect to the 00530 * initializing std::unique_ptr object. This is because such an 00531 * object is usually passed to this constructor as a temporary, which 00532 * is only visible and accessible in the thread carrying out the move 00533 * operation, in which case synchronization would represent pointless 00534 * overhead. In a case where the user uses std::move to force a move 00535 * from a named std::unique_ptr object, and that named object's 00536 * lifetime is managed by (or the object is otherwise accessed by) a 00537 * different thread than the one making the move, the user must carry 00538 * out her own synchronization with respect to that different thread, 00539 * as the initializing std::unique_ptr object will be mutated by the 00540 * move. 00541 * @note 3. If the library is compiled using the --with-auto-ptr 00542 * configuration option, then this constructor's signature is 00543 * JoinableHandle(std::auto_ptr<Cgu::Thread::Thread> thr, Action act) 00544 * in order to retain compatibility with the 1.2 series of the library 00545 * @sa JoinableHandle::is_managing(). 00546 */ 00547 #ifdef CGU_USE_AUTO_PTR 00548 JoinableHandle(std::auto_ptr<Cgu::Thread::Thread> thr, Action act): action(act), detached(false), thread(thr.release()) {} 00549 #else 00550 JoinableHandle(std::unique_ptr<Cgu::Thread::Thread> thr, Action act): action(act), detached(false), thread(std::move(thr)) {} 00551 #endif 00552 00553 /** 00554 * This constructor initializes a new JoinableHandle object with an 00555 * existing JoinableHandle object. This is a move operation which 00556 * transfers ownership to the new object. 00557 * @param h The initializing JoinableHandle object, which will cease 00558 * to hold a valid Thread::Thread object after the initialization has 00559 * taken place. 00560 * @exception Cgu::Thread::MutexError Throws this exception if 00561 * initialization of the internal mutex fails. The constructor is 00562 * strongly exception safe: if Cgu::Thread::MutexError is thrown, the 00563 * initializing Cgu::Thread::JoinableHandle object will be left 00564 * unchanged. (It is often not worth checking for this exception, as 00565 * it means either memory is exhausted or pthread has run out of other 00566 * resources to create new mutexes.) 00567 * @note 1. No synchronization is carried out with respect to the 00568 * initializing rvalue. This is because temporaries are only visible 00569 * and accessible in the thread carrying out the move operation and 00570 * synchronization for them would represent pointless overhead. In a 00571 * case where a user uses std::move to force a move from a named 00572 * object, and that named object's lifetime is managed by (or the 00573 * object is otherwise accessed by) a different thread than the one 00574 * making the move, the user must carry out her own synchronization 00575 * with respect to that different thread, as the named object will be 00576 * mutated by the move. 00577 * @note 2. If the library is compiled using the --with-auto-ptr 00578 * configuration option, then this constructor's signature is 00579 * JoinableHandle(JoinableHandle& h) in order to retain compatibility 00580 * with the 1.2 series of the library. 00581 */ 00582 #ifdef CGU_USE_AUTO_PTR 00583 JoinableHandle(JoinableHandle& h): action(h.action), detached(h.detached), thread(std::move(h.thread)) {} 00584 #else 00585 JoinableHandle(JoinableHandle&& h): action(h.action), detached(h.detached), thread(std::move(h.thread)) {} 00586 #endif 00587 00588 /** 00589 * The default constructor. Nothing is managed until the move 00590 * assignment operator has been called. 00591 * @exception Cgu::Thread::MutexError Throws this exception if 00592 * initialization of the internal mutex fails. (It is often not worth 00593 * checking for this exception, as it means either memory is exhausted 00594 * or pthread has run out of other resources to create new mutexes.) 00595 * 00596 * Since 2.0.8 00597 */ 00598 JoinableHandle(): action(detach_on_exit), detached(true) {} 00599 00600 /** 00601 * The destructor will detach a managed thread (if the 00602 * Thread::JoinableHandle::detach_on_exit flag is set) or join it (if 00603 * the Thread::JoinableHandle::join_on_exit flag is set), unless it 00604 * has previously been detached or joined with the detach() or join() 00605 * methods. The destructor is thread safe (any thread may destroy the 00606 * JoinableHandle object). The destructor will not throw. 00607 */ 00608 ~JoinableHandle(); 00609 00610 /* Only has effect if --with-glib-memory-slices-compat or 00611 * --with-glib-memory-slices-no-compat option picked */ 00612 CGU_GLIB_MEMORY_SLICES_FUNCS 00613 }; 00614 00615 /** 00616 * @class CancelBlock thread.h c++-gtk-utils/thread.h 00617 * @brief A class enabling the cancellation state of a thread to be 00618 * controlled. 00619 * 00620 * A class enabling the cancellation state of a thread to be 00621 * controlled, so as to provide exception safe cancellation state 00622 * changes. When the object goes out of scope, cancellation state is 00623 * returned to the state it was in prior to its construction. 00624 */ 00625 00626 class CancelBlock { 00627 int starting_state; 00628 public: 00629 /** 00630 * This class cannot be copied. The copy constructor is deleted. 00631 */ 00632 CancelBlock(const CancelBlock&) = delete; 00633 00634 /** 00635 * This class cannot be copied. The assignment operator is deleted. 00636 */ 00637 CancelBlock& operator=(const CancelBlock&) = delete; 00638 00639 /** 00640 * Makes the thread uncancellable, even if the code passes through a 00641 * cancellation point, while the CancelBlock object exists (when the 00642 * CancelBlock object ceases to exist, cancellation state is returned 00643 * to the state prior to it being constructed). It should only be 00644 * called by the thread which created the CancelBlock object. This 00645 * method will not throw. 00646 * @param old_state Indicates the cancellation state of the calling 00647 * thread immediately before this call to block() was made, either 00648 * PTHREAD_CANCEL_ENABLE (if the thread was previously cancellable) or 00649 * PTHREAD_CANCEL_DISABLE (if this call did nothing because the thread 00650 * was already uncancellable). 00651 * @return 0 if successful, else a value other than 0. 00652 */ 00653 static int block(int& old_state) {return pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);} 00654 00655 /** 00656 * Makes the thread uncancellable, even if the code passes through a 00657 * cancellation point, while the CancelBlock object exists (when the 00658 * CancelBlock object ceases to exist, cancellation state is returned 00659 * to the state prior to it being constructed). It should only be 00660 * called by the thread which created the CancelBlock object. This 00661 * method will not throw. 00662 * @return 0 if successful, else a value other than 0. 00663 */ 00664 static int block() {int old_state; return block(old_state);} 00665 00666 /** 00667 * Makes the thread cancellable while the CancelBlock object exists 00668 * (when the CancelBlock object ceases to exist, cancellation state is 00669 * returned to the state prior to it being constructed). It should 00670 * only be called by the thread which created the CancelBlock object. 00671 * This method will not throw. 00672 * @param old_state Indicates the cancellation state of the calling 00673 * thread immediately before this call to unblock() was made, either 00674 * PTHREAD_CANCEL_DISABLE (if the thread was previously uncancellable) 00675 * or PTHREAD_CANCEL_ENABLE (if this call did nothing because the 00676 * thread was already cancellable). 00677 * @return 0 if successful, else a value other than 0. 00678 */ 00679 static int unblock(int& old_state) {return pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);} 00680 00681 /** 00682 * Makes the thread cancellable while the CancelBlock object exists 00683 * (when the CancelBlock object ceases to exist, cancellation state is 00684 * returned to the state prior to it being constructed). It should 00685 * only be called by the thread which created the CancelBlock object. 00686 * This method will not throw. 00687 * @return 0 if successful, else a value other than 0. 00688 */ 00689 static int unblock() {int old_state; return unblock(old_state);} 00690 00691 /** 00692 * Restores cancellation state to the state it was in immediately 00693 * before this CancelBlock object was constructed. It should only be 00694 * called by the thread which created the CancelBlock object. This 00695 * method will not throw. 00696 * @param old_state Indicates the cancellation state of the calling 00697 * thread immediately before this call to restore() was made, either 00698 * PTHREAD_CANCEL_DISABLE (if the thread was previously uncancellable) 00699 * or PTHREAD_CANCEL_ENABLE (if this thread was previously 00700 * cancellable). 00701 * @return 0 if successful, else a value other than 0. 00702 */ 00703 int restore(int& old_state) {return pthread_setcancelstate(starting_state, &old_state);} 00704 00705 /** 00706 * Restores cancellation state to the state it was in immediately 00707 * before this CancelBlock object was constructed. It should only be 00708 * called by the thread which created the CancelBlock object. This 00709 * method will not throw. 00710 * @return 0 if successful, else a value other than 0. 00711 */ 00712 int restore() {int old_state; return restore(old_state);} 00713 00714 /** 00715 * The constructor will not throw. 00716 * @param blocking Whether the CancelBlock object should start 00717 * in blocking mode. 00718 */ 00719 CancelBlock(bool blocking = true); 00720 00721 /** 00722 * The destructor will put the thread in the cancellation state that 00723 * it was in immediately before the CancelBlock object was constructed 00724 * (which might be blocking). It will not throw. 00725 */ 00726 ~CancelBlock() {restore();} 00727 00728 /* Only has effect if --with-glib-memory-slices-compat or 00729 * --with-glib-memory-slices-no-compat option picked */ 00730 CGU_GLIB_MEMORY_SLICES_FUNCS 00731 }; 00732 00733 /** 00734 * @class Exit thread.h c++-gtk-utils/thread.h 00735 * @brief A class which can be thrown to terminate the throwing 00736 * thread. 00737 * 00738 * This class can be thrown (instead of calling pthread_exit()) when a 00739 * thread wishes to terminate itself and also ensure stack unwinding, 00740 * so that destructors of local objects are called. It is caught 00741 * automatically by the implementation of Cgu::Thread::Thread::start() 00742 * so that it will only terminate the thread throwing it and not the 00743 * whole process. See the Cgu::Thread::Thread::cancel() method above, 00744 * for use when a thread wishes to terminate another one, and the 00745 * caveats on the use of Cgu::Thread::Thread::cancel(). 00746 * 00747 * Do not throw a Cgu::Thread::Exit object in a program with more than 00748 * one main loop in order to terminate one of the threads which has 00749 * its own main loop. Instead, just cause its main loop to terminate 00750 * by, say, calling g_main_loop_quit() on it. 00751 */ 00752 class Exit {}; 00753 00754 } // namespace Thread 00755 00756 } // namespace Cgu 00757 00758 #endif