1///////////////////////////////////////////////////////////////////////////
2//
3// Copyright (c) 2005, 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 "IlmBaseConfig.h"
70
71#if defined _WIN32 || defined _WIN64
72    #ifdef NOMINMAX
73        #undef NOMINMAX
74    #endif
75    #define NOMINMAX
76    #include <windows.h>
77#elif HAVE_PTHREAD
78    #include <pthread.h>
79#endif
80
81namespace IlmThread {
82
83class Lock;
84
85
86class Mutex
87{
88  public:
89
90    Mutex ();
91    virtual ~Mutex ();
92
93  private:
94
95    void	lock () const;
96    void	unlock () const;
97
98    #if defined _WIN32 || defined _WIN64
99	mutable CRITICAL_SECTION _mutex;
100    #elif HAVE_PTHREAD
101	mutable pthread_mutex_t _mutex;
102    #endif
103
104    void operator = (const Mutex& M);	// not implemented
105    Mutex (const Mutex& M);		// not implemented
106
107    friend class Lock;
108};
109
110
111class Lock
112{
113  public:
114
115    Lock (const Mutex& m, bool autoLock = true):
116	_mutex (m),
117	_locked (false)
118    {
119        if (autoLock)
120        {
121            _mutex.lock();
122            _locked = true;
123        }
124    }
125
126    ~Lock ()
127    {
128        if (_locked)
129            _mutex.unlock();
130    }
131
132    void acquire ()
133    {
134        _mutex.lock();
135        _locked = true;
136    }
137
138    void release ()
139    {
140        _mutex.unlock();
141        _locked = false;
142    }
143
144    bool locked ()
145    {
146        return _locked;
147    }
148
149  private:
150
151    const Mutex &	_mutex;
152    bool		_locked;
153};
154
155
156} // namespace IlmThread
157
158#endif
159