• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

Mutex.h

Go to the documentation of this file.
00001 /**
00002   Licensed to the Apache Software Foundation (ASF) under one
00003   or more contributor license agreements.  See the NOTICE file
00004   distributed with this work for additional information
00005   regarding copyright ownership.  The ASF licenses this file
00006   to you under the Apache License, Version 2.0 (the
00007   "License"); you may not use this file except in compliance
00008   with the License.  You may obtain a copy of the License at
00009 
00010       http://www.apache.org/licenses/LICENSE-2.0
00011 
00012   Unless required by applicable law or agreed to in writing, software
00013   distributed under the License is distributed on an "AS IS" BASIS,
00014   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015   See the License for the specific language governing permissions and
00016   limitations under the License.
00017  */
00018 
00019 /**
00020  * @file Mutex.h
00021  * @brief Contains Mutex related classes for creating a Mutex and locking a Mutex in a specific scope.
00022  */
00023 
00024 #pragma once
00025 #ifndef ATSCPPAPI_MUTEX_H_
00026 #define ATSCPPAPI_MUTEX_H_
00027 
00028 #include <pthread.h>
00029 #include <atscppapi/noncopyable.h>
00030 #include <atscppapi/shared_ptr.h>
00031 
00032 namespace atscppapi {
00033 
00034 /**
00035  * @brief A mutex is mutual exclusion: a blocking lock.
00036  *
00037  * The Mutex class uses pthreads for its implmentation.
00038  *
00039  * @see ScopedMutexLock
00040  * @see ScopedMutexTryLock
00041  * @see ScopedSharedMutexLock
00042  * @see ScopedSharedMutexTryLock
00043  */
00044 class Mutex: noncopyable {
00045 public:
00046 
00047   /**
00048    * The available types of Mutexes.
00049    */
00050   enum Type {
00051     TYPE_NORMAL = 0, /**< This type of Mutex will deadlock if locked by a thread already holding the lock */
00052     TYPE_RECURSIVE, /**< This type of Mutex will allow a thread holding the lock to lock it again; however, it must be unlocked the same number of times */
00053     TYPE_ERROR_CHECK /**< This type of Mutex will return errno = EDEADLCK if a thread would deadlock by taking the lock after it already holds it */
00054   };
00055 
00056   /**
00057    * Create a mutex
00058    *
00059    * @param type The Type of Mutex to create, the default is TYPE_NORMAL.
00060    * @see Type
00061    */
00062   Mutex(Type type = TYPE_NORMAL) {
00063     pthread_mutexattr_t attr;
00064     pthread_mutexattr_init(&attr);
00065 
00066     switch(type) {
00067     case TYPE_RECURSIVE:
00068      pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
00069      break;
00070     case TYPE_ERROR_CHECK:
00071      pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
00072      break;
00073     case TYPE_NORMAL:
00074     default:
00075      pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
00076      break;
00077     }
00078 
00079     pthread_mutex_init(&mutex, &attr);
00080   }
00081 
00082   ~Mutex() {
00083     pthread_mutex_destroy(&mutex);
00084   }
00085 
00086   /**
00087    * Try to take the lock, this call will NOT block if the mutex cannot be taken.
00088    * @return Returns true if the lock was taken, false if it was not. This call obviously will not block.
00089    */
00090   bool tryLock() {
00091     return !pthread_mutex_trylock(&mutex);
00092   }
00093 
00094   /**
00095    * Block until the lock is taken, when this call returns the thread will be holding the lock.
00096    */
00097   void lock() {
00098     pthread_mutex_lock(&mutex);
00099   }
00100 
00101   /**
00102    * Unlock the lock, this call is nonblocking.
00103    */
00104   void unlock() {
00105     pthread_mutex_unlock(&mutex);
00106   }
00107 private:
00108   pthread_mutex_t mutex; /**< Internal mutex identifier */
00109 };
00110 
00111 /**
00112  * @brief Take a Mutex reference and lock inside a scope and unlock when the scope is exited.
00113  *
00114  * This is an RAII implementation which will lock a mutex at the start of the
00115  * scope and unlock it when the scope is exited.
00116  *
00117  * @see Mutex
00118  */
00119 class ScopedMutexLock: noncopyable {
00120 public:
00121   /**
00122    * Create the scoped mutex lock, once this object is constructed the lock will be held by the thread.
00123    * @param mutex a reference to a Mutex.
00124    */
00125   explicit ScopedMutexLock(Mutex &mutex) :
00126       mutex_(mutex) {
00127     mutex_.lock();
00128   }
00129 
00130   /**
00131    * Unlock the mutex.
00132    */
00133   ~ScopedMutexLock() {
00134     mutex_.unlock();
00135   }
00136 private:
00137   Mutex &mutex_;
00138 };
00139 
00140 /**
00141  * @brief Take a shared_ptr to a Mutex and lock inside a scope and unlock when the scope is exited.
00142  *
00143  * This is an RAII implementation which will lock a mutex at the start of the
00144  * scope and unlock it when the scope is exited.
00145  *
00146  * @see Mutex
00147  */
00148 class ScopedSharedMutexLock: noncopyable {
00149 public:
00150   /**
00151    * Create the scoped mutex lock, once this object is constructed the lock will be held by the thread.
00152    * @param mutex a shared pointer to a Mutex.
00153    */
00154   explicit ScopedSharedMutexLock(shared_ptr<Mutex> mutex) :
00155       mutex_(mutex) {
00156     mutex_->lock();
00157   }
00158 
00159   /**
00160    * Unlock the mutex.
00161    */
00162   ~ScopedSharedMutexLock() {
00163     mutex_->unlock();
00164   }
00165 private:
00166   shared_ptr<Mutex> mutex_;
00167 };
00168 
00169 /**
00170  * @brief Take a Mutex reference and try to lock inside a scope and unlock when the scope is exited (if the lock was taken).
00171  *
00172  * This is an RAII implementation which will lock a mutex at the start of the
00173  * scope and unlock it when the scope is exited if the lock was taken.
00174  *
00175  * @see Mutex
00176  */
00177 class ScopedMutexTryLock: noncopyable {
00178 public:
00179   /**
00180    * Try to create the scoped mutex lock, if you should check hasLock() to determine if this object was successfully able to take the lock.
00181    * @param mutex a shared pointer to a Mutex.
00182    */
00183   explicit ScopedMutexTryLock(Mutex &mutex) :
00184       mutex_(mutex), has_lock_(false) {
00185     has_lock_ = mutex_.tryLock();
00186   }
00187 
00188   /**
00189    * Unlock the mutex (if we hold the lock)
00190    */
00191   ~ScopedMutexTryLock() {
00192     if (has_lock_) {
00193       mutex_.unlock();
00194     }
00195   }
00196 
00197   /**
00198    * @return True if the lock was taken, False if it was not taken.
00199    */
00200   bool hasLock() {
00201     return has_lock_;
00202   }
00203 private:
00204   Mutex &mutex_;
00205   bool has_lock_;
00206 };
00207 
00208 /**
00209  * @brief Take a shared_ptr to a Mutex and try to lock inside a scope and unlock when the scope is exited (if the lock was taken).
00210  *
00211  * This is an RAII implementation which will lock a mutex at the start of the
00212  * scope and unlock it when the scope is exited if the lock was taken.
00213  *
00214  * @see Mutex
00215  */
00216 class ScopedSharedMutexTryLock: noncopyable {
00217 public:
00218   /**
00219    * Try to create the scoped mutex lock, if you should check hasLock() to determine if this object was successfully able to take the lock.
00220    * @param mutex a shared pointer to a Mutex.
00221    */
00222   explicit ScopedSharedMutexTryLock(shared_ptr<Mutex> mutex) :
00223       mutex_(mutex), has_lock_(false) {
00224     has_lock_ = mutex_->tryLock();
00225   }
00226 
00227   /**
00228    * Unlock the mutex (if we hold the lock)
00229    */
00230   ~ScopedSharedMutexTryLock() {
00231     if (has_lock_) {
00232       mutex_->unlock();
00233     }
00234   }
00235 
00236   /**
00237    * @return True if the lock was taken, False if it was not taken.
00238    */
00239   bool hasLock() {
00240     return has_lock_;
00241   }
00242 private:
00243   shared_ptr<Mutex> mutex_;
00244   bool has_lock_;
00245 };
00246 
00247 } /* atscppapi */
00248 
00249 
00250 #endif /* ATSCPPAPI_MUTEX_H_ */

Generated by  doxygen 1.7.1