smart_mutex.h

Go to the documentation of this file.
00001 /*
00002  * smart_mutex.h
00003  *
00004  * Copyright (C) 2007,2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Simple smart mutex object.
00032  */
00033 
00034 #ifndef WAVEPACKET_THREADSAFE_SMART_MUTEX_H__
00035 #define WAVEPACKET_THREADSAFE_SMART_MUTEX_H__
00036 
00037 // includes --------------------------------------------------------------------
00038 #include "common/common.h"
00039 
00040 #ifdef WIN32
00041 typedef CRITICAL_SECTION        mutex_t;
00042 #else   // WIN32
00043 #include <pthread.h>
00044 typedef pthread_mutex_t         mutex_t;
00045 #endif  // WIN32
00046 
00047 /// \ingroup threading
00048 /*@{*/
00049 
00050 /// \defgroup threadsafe Threadsafe Collection API
00051 ///
00052 /// A set of objects and collection for threadsafe C++ code.
00053 /// Abstracts lower-level threadsafe objects.
00054 /*@{*/
00055 
00056 
00057 /// class that automatically creates and destroys mutexes
00058 class smart_mutex {
00059 public:
00060         /// constructor will automatically create mutex
00061         smart_mutex(void) {
00062 #ifdef WIN32
00063                         // use spin count, can help multi-proc
00064                         // (spin count is ignored on single-proc machines)
00065                         InitializeCriticalSectionAndSpinCount(&m_mutex, 4096);
00066 #else   // WIN32
00067                         ASSERT(!pthread_mutex_init(&m_mutex, NULL),
00068                             "Failed to initialize mutex");
00069 #endif  // WIN32
00070                 }
00071 
00072         /// destructor will automatically destroy mutex
00073         ~smart_mutex(void) {
00074 #ifdef WIN32
00075                         DeleteCriticalSection(&m_mutex);
00076 #else   // WIN32
00077                         pthread_mutex_destroy(&m_mutex);
00078 #endif  // WIN32
00079                 }
00080 
00081         /// operating-system-dependent accessor
00082         mutex_t * getMutex(void) { return &m_mutex; }
00083 
00084 private:
00085         // private member data
00086         mutex_t         m_mutex;
00087 };
00088 
00089 
00090 
00091 /// class that automatically locks and unlocks pthread mutexes
00092 /// To use mlocks in code:
00093 ///   - create smart_mutex that will be locked
00094 ///   - create an mlock object and pass the mutex in the constructor
00095 ///   - on destruction, the mlock will automatically unlock the mutex
00096 ///
00097 /// Example:
00098 ///\code
00099 ///     void threadsafeFunction(void)
00100 ///     {
00101 ///             smart_mutex my_mutex;
00102 ///
00103 ///             mlock lock(my_mutex);   // blocks until mutex is acquired
00104 ///
00105 ///             // some stuff that needs to be protected happens here
00106 ///             ...
00107 ///
00108 ///     }  <--- mutex is unlocked here as mlock destructor is called
00109 ///\endcode
00110 class mlock {
00111 public:
00112         /// constructor that accepts smart_mutex
00113         mlock(IN smart_mutex& sm) {
00114                         mutex_t * pm = sm.getMutex();
00115                         if (pm) {
00116                                 m_pMutex = pm;
00117 #ifdef WIN32
00118                                 EnterCriticalSection(pm);
00119 #else   // WIN32
00120                                 pthread_mutex_lock(pm);
00121 #endif  // WIN32
00122                         }
00123                 }
00124 
00125         /// destructor automatically unlocks
00126         ~mlock(void) {
00127                         if (m_pMutex) {
00128 #ifdef WIN32
00129                                 LeaveCriticalSection(m_pMutex);
00130 #else   // WIN32
00131                                 pthread_mutex_unlock(m_pMutex);
00132 #endif  // WIN32
00133                         }
00134                 }
00135 
00136 private:
00137         // private helper methods
00138         mlock(void);
00139         mlock(IN const mlock&);
00140 
00141         // private member data -------------------------------------------------
00142         mutex_t *       m_pMutex;
00143 };
00144 
00145 
00146 
00147 #endif  // WAVEPACKET_THREADSAFE_SMART_MUTEX_H__
00148