Fawkes API Fawkes Development Version

mutex_locker.cpp

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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends