1 /////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas 4 // Digital Ltd. LLC 5 // 6 // All rights reserved. 7 // 8 // Redistribution and use in source and binary forms, with or without 9 // modification, are permitted provided that the following conditions are 10 // met: 11 // * Redistributions of source code must retain the above copyright 12 // notice, this list of conditions and the following disclaimer. 13 // * Redistributions in binary form must reproduce the above 14 // copyright notice, this list of conditions and the following disclaimer 15 // in the documentation and/or other materials provided with the 16 // distribution. 17 // * Neither the name of Industrial Light & Magic nor the names of 18 // its contributors may be used to endorse or promote products derived 19 // from this software without specific prior written permission. 20 // 21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 // 33 /////////////////////////////////////////////////////////////////////////// 34 35 #ifndef INCLUDED_ILM_THREAD_MUTEX_H 36 #define INCLUDED_ILM_THREAD_MUTEX_H 37 38 //----------------------------------------------------------------------------- 39 // 40 // class Mutex, class Lock 41 // 42 // Class Mutex is a wrapper for a system-dependent mutual exclusion 43 // mechanism. Actual locking and unlocking of a Mutex object must 44 // be performed using an instance of a Lock (defined below). 45 // 46 // Class lock provides safe locking and unlocking of mutexes even in 47 // the presence of C++ exceptions. Constructing a Lock object locks 48 // the mutex; destroying the Lock unlocks the mutex. 49 // 50 // Lock objects are not themselves thread-safe. You should never 51 // share a Lock object among multiple threads. 52 // 53 // Typical usage: 54 // 55 // Mutex mtx; // Create a Mutex object that is visible 56 // //to multiple threads 57 // 58 // ... // create some threads 59 // 60 // // Then, within each thread, construct a critical section like so: 61 // 62 // { 63 // Lock lock (mtx); // Lock constructor locks the mutex 64 // ... // do some computation on shared data 65 // } // leaving the block unlocks the mutex 66 // 67 //----------------------------------------------------------------------------- 68 69 #include "IlmThreadExport.h" 70 #include "IlmBaseConfig.h" 71 #include "IlmThreadNamespace.h" 72 73 #ifdef ILMBASE_FORCE_CXX03 74 # if defined _WIN32 || defined _WIN64 75 # ifdef NOMINMAX 76 # undef NOMINMAX 77 # endif 78 # define NOMINMAX 79 # include <windows.h> 80 # elif HAVE_PTHREAD 81 # include <pthread.h> 82 # endif 83 #else 84 # include <mutex> 85 #endif 86 87 ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER 88 89 90 // in c++11, this can just be 91 // 92 // using Mutex = std::mutex; 93 // unfortunately we can't use std::unique_lock as a replacement for Lock since 94 // they have different API. 95 // 96 // if we decide to break the API, we can just 97 // 98 // using Lock = std::lock_guard<std::mutex>; 99 // or 100 // using Lock = std::unique_lock<std::mutex>; 101 // 102 // (or eliminate the type completely and have people use the std library) 103 #ifdef ILMBASE_FORCE_CXX03 104 105 class Lock; 106 107 class ILMTHREAD_EXPORT Mutex 108 { 109 public: 110 111 Mutex (); 112 virtual ~Mutex (); 113 114 private: 115 116 void lock () const; 117 void unlock () const; 118 119 #if defined _WIN32 || defined _WIN64 120 mutable CRITICAL_SECTION _mutex; 121 #elif HAVE_PTHREAD 122 mutable pthread_mutex_t _mutex; 123 #endif 124 125 void operator = (const Mutex& M); // not implemented 126 Mutex (const Mutex& M); // not implemented 127 128 friend class Lock; 129 }; 130 #else 131 using Mutex = std::mutex; 132 #endif 133 134 class ILMTHREAD_EXPORT Lock 135 { 136 public: 137 138 Lock (const Mutex& m, bool autoLock = true): _mutex(const_cast<Mutex &> (m))139 _mutex (const_cast<Mutex &>(m)), _locked (false) 140 { 141 if (autoLock) 142 { 143 _mutex.lock(); 144 _locked = true; 145 } 146 } 147 ~Lock()148 ~Lock () 149 { 150 if (_locked) 151 _mutex.unlock(); 152 } 153 acquire()154 void acquire () 155 { 156 _mutex.lock(); 157 _locked = true; 158 } 159 release()160 void release () 161 { 162 _mutex.unlock(); 163 _locked = false; 164 } 165 locked()166 bool locked () 167 { 168 return _locked; 169 } 170 171 private: 172 173 Mutex & _mutex; 174 bool _locked; 175 }; 176 177 178 ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT 179 180 #endif // INCLUDED_ILM_THREAD_MUTEX_H 181