2 Copyright 2005-2011 Intel Corporation. All Rights Reserved.
4 This file is part of Threading Building Blocks.
6 Threading Building Blocks is free software; you can redistribute it
7 and/or modify it under the terms of the GNU General Public License
8 version 2 as published by the Free Software Foundation.
10 Threading Building Blocks is distributed in the hope that it will be
11 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with Threading Building Blocks; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 As a special exception, you may use this file as part of a free software
20 library without restriction. Specifically, if other files instantiate
21 templates or use macros or inline functions from this file, or you compile
22 this file and link it with other files to produce an executable, this
23 file does not by itself cause the resulting executable to be covered by
24 the GNU General Public License. This exception does not however
25 invalidate any other reasons why the executable file might be covered by
26 the GNU General Public License.
33 #include "machine/windows_api.h"
36 #endif /* _WIN32||_WIN64 */
39 #include "aligned_space.h"
40 #include "tbb_stddef.h"
41 #include "tbb_profiling.h"
45 //! Wrapper around the platform's native reader-writer lock.
46 /** For testing purposes only.
47 @ingroup synchronization */
50 //! Construct unacquired mutex.
52 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
56 InitializeCriticalSection(&impl);
58 int error_code = pthread_mutex_init(&impl,NULL);
60 tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_init failed");
61 #endif /* _WIN32||_WIN64*/
62 #endif /* TBB_USE_ASSERT */
70 DeleteCriticalSection(&impl);
72 pthread_mutex_destroy(&impl);
74 #endif /* _WIN32||_WIN64 */
75 #endif /* TBB_USE_ASSERT */
79 friend class scoped_lock;
81 //! The scoped locking pattern
82 /** It helps to avoid the common problem of forgetting to release lock.
83 It also nicely provides the "node" for queuing locks. */
84 class scoped_lock : internal::no_copy {
86 //! Construct lock that has not acquired a mutex.
87 scoped_lock() : my_mutex(NULL) {};
89 //! Acquire lock on given mutex.
90 scoped_lock( mutex& mutex ) {
94 //! Release lock (if lock is held).
100 //! Acquire lock on given mutex.
101 void acquire( mutex& mutex ) {
103 internal_acquire(mutex);
107 #endif /* TBB_USE_ASSERT */
110 //! Try acquire lock on given mutex.
111 bool try_acquire( mutex& mutex ) {
113 return internal_try_acquire (mutex);
115 bool result = mutex.try_lock();
119 #endif /* TBB_USE_ASSERT */
129 #endif /* TBB_USE_ASSERT */
133 //! The pointer to the current mutex to work
136 //! All checks from acquire using mutex.state were moved here
137 void __TBB_EXPORTED_METHOD internal_acquire( mutex& m );
139 //! All checks from try_acquire using mutex.state were moved here
140 bool __TBB_EXPORTED_METHOD internal_try_acquire( mutex& m );
142 //! All checks from release using mutex.state were moved here
143 void __TBB_EXPORTED_METHOD internal_release();
149 static const bool is_rw_mutex = false;
150 static const bool is_recursive_mutex = false;
151 static const bool is_fair_mutex = false;
153 // ISO C++0x compatibility methods
158 aligned_space<scoped_lock,1> tmp;
159 new(tmp.begin()) scoped_lock(*this);
162 EnterCriticalSection(&impl);
164 pthread_mutex_lock(&impl);
165 #endif /* _WIN32||_WIN64 */
166 #endif /* TBB_USE_ASSERT */
169 //! Try acquiring lock (non-blocking)
170 /** Return true if lock acquired; false otherwise. */
173 aligned_space<scoped_lock,1> tmp;
174 scoped_lock& s = *tmp.begin();
176 return s.internal_try_acquire(*this);
179 return TryEnterCriticalSection(&impl)!=0;
181 return pthread_mutex_trylock(&impl)==0;
182 #endif /* _WIN32||_WIN64 */
183 #endif /* TBB_USE_ASSERT */
189 aligned_space<scoped_lock,1> tmp;
190 scoped_lock& s = *tmp.begin();
192 s.internal_release();
195 LeaveCriticalSection(&impl);
197 pthread_mutex_unlock(&impl);
198 #endif /* _WIN32||_WIN64 */
199 #endif /* TBB_USE_ASSERT */
202 //! Return native_handle
204 typedef LPCRITICAL_SECTION native_handle_type;
206 typedef pthread_mutex_t* native_handle_type;
208 native_handle_type native_handle() { return (native_handle_type) &impl; }
217 CRITICAL_SECTION impl;
220 pthread_mutex_t impl;
221 #endif /* _WIN32||_WIN64 */
223 //! All checks from mutex constructor using mutex.state were moved here
224 void __TBB_EXPORTED_METHOD internal_construct();
226 //! All checks from mutex destructor using mutex.state were moved here
227 void __TBB_EXPORTED_METHOD internal_destroy();
231 //! Set the internal state
232 void set_state( state_t to ) { state = to; }
236 __TBB_DEFINE_PROFILING_SET_NAME(mutex)
240 #endif /* __TBB_mutex_H */