mutex.cpp

00001 
00002 /***************************************************************************
00003  *  mutex.cpp - implementation of mutex, based on pthreads
00004  *
00005  *  Generated: Thu Sep 14 17:03:57 2006
00006  *  Copyright  2006  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.h>
00025 #include <core/threading/mutex_data.h>
00026 #include <core/threading/thread.h>
00027 #include <core/exception.h>
00028 
00029 #include <pthread.h>
00030 
00031 namespace fawkes {
00032 
00033 /** @class Mutex core/threading/mutex.h
00034  * Mutex mutual exclusion lock.
00035  * This class is used in a multi-threading environment to lock access to
00036  * resources. This is needed to prevent two threads from modifying a value
00037  * at the same time or to prevent a thread from getting a dirty copy of
00038  * a piece of data (the reader reads while a writer is writing, this could
00039  * leave the data in a state where the reader reads half of the new and half
00040  * of the old data).
00041  *
00042  * As a rule of thumb you should lock the mutex as short as possible and as
00043  * long as needed. Locking the mutex too long will lead in a bad performance
00044  * of the multi-threaded application because many threads are waiting for
00045  * the lock and are not doing anything useful.
00046  * If you do not lock enough code (and so serialize it) it will cause pain
00047  * and errors.
00048  *
00049  * @ingroup Threading
00050  * @ingroup FCL
00051  * @see example_mutex_count.cpp
00052  *
00053  * @author Tim Niemueller
00054  */
00055 
00056 
00057 /** Constructor */
00058 Mutex::Mutex()
00059 {
00060   mutex_data = new MutexData();
00061   pthread_mutex_init(&(mutex_data->mutex), NULL);
00062 }
00063 
00064 /** Destructor */
00065 Mutex::~Mutex()
00066 {
00067   pthread_mutex_destroy(&(mutex_data->mutex));
00068   delete mutex_data;
00069   mutex_data = NULL;
00070 }
00071 
00072 
00073 /** Lock this mutex.
00074  * A call to lock() will block until the lock on the mutex could be aquired.
00075  * If you want to avoid see consider using try_lock().
00076  */
00077 void
00078 Mutex::lock()
00079 {
00080   int err = 0;
00081   if ( (err = pthread_mutex_lock(&(mutex_data->mutex))) != 0 ) {
00082     throw Exception(err, "Failed to aquire lock for thread %s", Thread::current_thread()->name());
00083   }
00084 #ifdef DEBUG_THREADING
00085   // do not switch order, lock holder must be protected with this mutex!
00086   mutex_data->set_lock_holder();
00087 #endif
00088 }
00089 
00090 
00091 /** Tries to lock the mutex.
00092  * This can also be used to check if a mutex is locked. The code for this
00093  * can be:
00094  *
00095  * @code
00096  * bool locked = false;
00097  * if ( mutex->try_lock() ) {
00098  *   mutex->unlock();
00099  *   locked = true;
00100  * }
00101  * @endcode
00102  *
00103  * This cannot be implemented in Mutex in a locked() method since this
00104  * would lead to race conditions in many situations.
00105  *
00106  * @return true, if the mutex could be locked, false otherwise.
00107  */
00108 bool
00109 Mutex::try_lock()
00110 {
00111   if (pthread_mutex_trylock(&(mutex_data->mutex)) == 0) {
00112 #ifdef DEBUG_THREADING
00113     mutex_data->set_lock_holder();
00114 #endif
00115     return true;
00116   } else {
00117     return false;
00118   }
00119 }
00120 
00121 
00122 /** Unlock the mutex. */
00123 void
00124 Mutex::unlock()
00125 {
00126 #ifdef DEBUG_THREADING
00127   mutex_data->unset_lock_holder();
00128   // do not switch order, lock holder must be protected with this mutex!
00129 #endif
00130   pthread_mutex_unlock(&(mutex_data->mutex));
00131 }
00132 
00133 
00134 /** Shortly stop by at the mutex.
00135  * This will just lock and unlock the mutex. It is equivalent to
00136  * @code
00137  *   mutex->lock();
00138  *   mutex->unlock();
00139  * @endcode
00140  * This can be handy if you have to protect starvation and just have a stop-by
00141  * mutex.
00142  */
00143 void
00144 Mutex::stopby()
00145 {
00146   pthread_mutex_lock(&(mutex_data->mutex));
00147   pthread_mutex_unlock(&(mutex_data->mutex));
00148 }
00149 
00150 
00151 } // end namespace fawkes

Generated on Tue Feb 22 13:31:25 2011 for Fawkes API by  doxygen 1.4.7