Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * mutex_locker.cpp - mutex locker helper 00004 * 00005 * Created: Thu Oct 04 16:14:30 2007 00006 * Copyright 2006-2007 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <core/threading/mutex_locker.h> 00025 #include <core/threading/mutex.h> 00026 00027 namespace fawkes { 00028 00029 /** @class MutexLocker <core/threading/mutex_locker.h> 00030 * Mutex locking helper. 00031 * This class is a convenience function which can help you prevent a quite 00032 * a few headaches. Consider the following code. 00033 * @code 00034 * void my_function() 00035 * { 00036 * mutex->lock(); 00037 * for (int i = 0; i < LIMIT; ++i) { 00038 * if ( failure ) { 00039 * mutex->unlock 00040 * } 00041 * } 00042 * 00043 * switch ( someval ) { 00044 * VALA: 00045 * mutex->unlock(); 00046 * return; 00047 * VALB: 00048 * do_something(); 00049 * } 00050 * 00051 * try { 00052 * do_function_that_throws_exceptions(); 00053 * } catch (Exception &e) { 00054 * mutex->unlock(); 00055 * throw; 00056 * } 00057 * mutex->unlock(); 00058 * } 00059 * @endcode 00060 * This is not a complete list of examples but as you see if you have many 00061 * exit points in a function it becomes more and more work to have correct 00062 * locking behavior. 00063 * 00064 * This is a lot simpler with the MutexLocker. The MutexLocker locks the 00065 * given mutex on creation, and unlocks it in the destructor. If you now 00066 * have a mutex locker on the stack as integral type the destructor is 00067 * called automagically on function exit and thus the mutex is appropriately 00068 * unlocked. 00069 * The code would look like this: 00070 * @code 00071 * void my_function() 00072 * { 00073 * MutexLocker ml(mutex); 00074 * // do anything, no need to call mutex->lock()/unlock() if only has to be 00075 * // called on entering and exiting the function. 00076 * } 00077 * @endcode 00078 * 00079 * @ingroup Threading 00080 * @ingroup FCL 00081 * 00082 * @author Tim Niemueller 00083 */ 00084 00085 00086 /** Constructor. 00087 * @param mutex Mutex to lock/unlock appropriately. 00088 * @param initially_lock true to lock the mutex in the constructor, false to not lock 00089 */ 00090 MutexLocker::MutexLocker(RefPtr<Mutex> mutex, bool initially_lock) 00091 { 00092 __rawmutex = 0; 00093 __refmutex = mutex; 00094 if ( initially_lock ) { 00095 __refmutex->lock(); 00096 } 00097 __locked = initially_lock; 00098 } 00099 00100 00101 /** Constructor. 00102 * @param mutex Mutex to lock/unlock appropriately. 00103 * @param initially_lock true to lock the mutex in the constructor, false to not lock 00104 */ 00105 MutexLocker::MutexLocker(Mutex *mutex, bool initially_lock) 00106 { 00107 __rawmutex = mutex; 00108 if ( initially_lock ) { 00109 __rawmutex->lock(); 00110 } 00111 __locked = initially_lock; 00112 } 00113 00114 00115 /** Destructor */ 00116 MutexLocker::~MutexLocker() 00117 { 00118 if ( __locked ) { 00119 if ( __rawmutex) { 00120 __rawmutex->unlock(); 00121 } else { 00122 __refmutex->unlock(); 00123 } 00124 } 00125 } 00126 00127 00128 /** Lock this mutex, again. 00129 * Use this if you unlocked the mutex from the outside. 00130 */ 00131 void 00132 MutexLocker::relock() 00133 { 00134 if ( __rawmutex ) { 00135 __rawmutex->lock(); 00136 } else { 00137 __refmutex->lock(); 00138 } 00139 __locked = true; 00140 } 00141 00142 00143 /** Unlock the mutex. */ 00144 void 00145 MutexLocker::unlock() 00146 { 00147 __locked = false; 00148 if ( __rawmutex ) { 00149 __rawmutex->unlock(); 00150 } else { 00151 __refmutex->unlock(); 00152 } 00153 } 00154 00155 00156 } // end namespace fawkes