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