read_write_lock.cpp

00001 
00002 /***************************************************************************
00003  *  read_write_lock.cpp - Read Write Lock
00004  *
00005  *  Generated: Thu Sep 15 00:10:54 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/read_write_lock.h>
00025 
00026 #include <pthread.h>
00027 #include <cstring>
00028 
00029 namespace fawkes {
00030 
00031 
00032 /// @cond INTERNALS
00033 class ReadWriteLockData
00034 {
00035  public:
00036   pthread_rwlock_t rwlock;
00037 };
00038 /// @endcond
00039 
00040 
00041 /** @class ReadWriteLock core/threading/read_write_lock.h
00042  * Read/write lock to allow multiple readers but only a single writer
00043  * on the resource at a time.
00044  * This can be used if you have a value that only a few writers modify but
00045  * several readers use. In this case the readers can read all at the same
00046  * time as long as there is no writer modifying the value.
00047  *
00048  * @ingroup Threading
00049  * @ingroup FCL
00050  * @see example_rwlock.cpp
00051  *
00052  * @author Tim Niemueller
00053  */
00054 
00055 
00056 /** Constructor
00057  * @param policy The read/write lock policy to use. The default is to
00058  * prefer writers.
00059  */
00060 ReadWriteLock::ReadWriteLock(ReadWriteLockPolicy policy)
00061 {
00062   rwlock_data = new ReadWriteLockData();
00063 
00064 #if defined __USE_UNIX98 || defined __USE_XOPEN2K
00065   pthread_rwlockattr_t attr;
00066   pthread_rwlockattr_init( &attr );
00067 
00068   switch (policy) {
00069   case RWLockPolicyPreferWriter:
00070     pthread_rwlockattr_setkind_np( &attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP );
00071     break;
00072   case RWLockPolicyPreferReader:
00073     pthread_rwlockattr_setkind_np( &attr, PTHREAD_RWLOCK_PREFER_READER_NP );
00074     break;
00075   }
00076 
00077   pthread_rwlock_init( &(rwlock_data->rwlock), &attr );
00078 #else
00079   pthread_rwlock_init( &(rwlock_data->rwlock), NULL );
00080 #endif
00081 }
00082 
00083 
00084 /** Destructor */
00085 ReadWriteLock::~ReadWriteLock()
00086 {
00087   pthread_rwlock_destroy( &(rwlock_data->rwlock) );
00088   delete rwlock_data;
00089 }
00090 
00091 
00092 /** Aquire a reader lock.
00093  * This will aquire the lock for reading. Multiple readers can aquire the
00094  * lock at the same time. But never when a writer has the lock.
00095  * This method will block until the lock has been aquired.
00096  */
00097 void
00098 ReadWriteLock::lock_for_read()
00099 {
00100   pthread_rwlock_rdlock( &(rwlock_data->rwlock) );
00101 }
00102 
00103 
00104 /** Aquire a writer lock.
00105  * This will aquire the lock for writing. Only a single writer at a time
00106  * will be allowed to aquire the lock.
00107  * This method will block until the lock has been aquired.
00108  */
00109 void
00110 ReadWriteLock::lock_for_write()
00111 {
00112   pthread_rwlock_wrlock( &(rwlock_data->rwlock) );
00113 }
00114 
00115 
00116 /** Tries to aquire a reader lock.
00117  * This will try to aquire the lock for reading. This will succeed if
00118  * no writer has aquired the lock already. Multiple readers may aquire the
00119  * lock.
00120  * @return true, if the lock could be aquired, false otherwise.
00121  */
00122 bool
00123 ReadWriteLock::try_lock_for_read()
00124 {
00125   return ( pthread_rwlock_tryrdlock( &(rwlock_data->rwlock) ) == 0 );
00126 }
00127 
00128 
00129 /** Tries to aquire a writer lock.
00130  * This will try to aquire the lock for writing. This will succeed if the
00131  * read/write lock is currently unlocked. No other threads may hold this lock
00132  * at the same time. Neither for writing nor for reading.
00133  * @return true, if the lock has been aquired, false otherwise.
00134  */
00135 bool
00136 ReadWriteLock::try_lock_for_write()
00137 {
00138   return ( pthread_rwlock_trywrlock( &(rwlock_data->rwlock) ) == 0 );
00139 }
00140 
00141 
00142 /** Release the lock.
00143  * Releases the lock, no matter whether it was locked for reading or writing.
00144  */
00145 void
00146 ReadWriteLock::unlock()
00147 {
00148   pthread_rwlock_unlock( &(rwlock_data->rwlock) );
00149 }
00150 
00151 
00152 } // end namespace fawkes