2 Copyright 2005-2010 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.
34 #if !defined(_WIN32_WINNT)
35 // The following Windows API function is declared explicitly;
36 // otherwise any user would have to specify /D_WIN32_WINNT=0x0400
37 extern "C" BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION );
39 #else /* if not _WIN32||_WIN64 */
41 #endif /* _WIN32||_WIN64 */
44 #include "aligned_space.h"
45 #include "tbb_stddef.h"
46 #include "tbb_profiling.h"
50 //! Wrapper around the platform's native reader-writer lock.
51 /** For testing purposes only.
52 @ingroup synchronization */
55 //! Construct unacquired mutex.
57 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
61 InitializeCriticalSection(&impl);
63 int error_code = pthread_mutex_init(&impl,NULL);
65 tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_init failed");
66 #endif /* _WIN32||_WIN64*/
67 #endif /* TBB_USE_ASSERT */
75 DeleteCriticalSection(&impl);
77 pthread_mutex_destroy(&impl);
79 #endif /* _WIN32||_WIN64 */
80 #endif /* TBB_USE_ASSERT */
84 friend class scoped_lock;
86 //! The scoped locking pattern
87 /** It helps to avoid the common problem of forgetting to release lock.
88 It also nicely provides the "node" for queuing locks. */
89 class scoped_lock : internal::no_copy {
91 //! Construct lock that has not acquired a mutex.
92 scoped_lock() : my_mutex(NULL) {};
94 //! Acquire lock on given mutex.
95 scoped_lock( mutex& mutex ) {
99 //! Release lock (if lock is held).
105 //! Acquire lock on given mutex.
106 void acquire( mutex& mutex ) {
108 internal_acquire(mutex);
112 #endif /* TBB_USE_ASSERT */
115 //! Try acquire lock on given mutex.
116 bool try_acquire( mutex& mutex ) {
118 return internal_try_acquire (mutex);
120 bool result = mutex.try_lock();
124 #endif /* TBB_USE_ASSERT */
134 #endif /* TBB_USE_ASSERT */
138 //! The pointer to the current mutex to work
141 //! All checks from acquire using mutex.state were moved here
142 void __TBB_EXPORTED_METHOD internal_acquire( mutex& m );
144 //! All checks from try_acquire using mutex.state were moved here
145 bool __TBB_EXPORTED_METHOD internal_try_acquire( mutex& m );
147 //! All checks from release using mutex.state were moved here
148 void __TBB_EXPORTED_METHOD internal_release();
154 static const bool is_rw_mutex = false;
155 static const bool is_recursive_mutex = false;
156 static const bool is_fair_mutex = false;
158 // ISO C++0x compatibility methods
163 aligned_space<scoped_lock,1> tmp;
164 new(tmp.begin()) scoped_lock(*this);
167 EnterCriticalSection(&impl);
169 pthread_mutex_lock(&impl);
170 #endif /* _WIN32||_WIN64 */
171 #endif /* TBB_USE_ASSERT */
174 //! Try acquiring lock (non-blocking)
175 /** Return true if lock acquired; false otherwise. */
178 aligned_space<scoped_lock,1> tmp;
179 scoped_lock& s = *tmp.begin();
181 return s.internal_try_acquire(*this);
184 return TryEnterCriticalSection(&impl)!=0;
186 return pthread_mutex_trylock(&impl)==0;
187 #endif /* _WIN32||_WIN64 */
188 #endif /* TBB_USE_ASSERT */
194 aligned_space<scoped_lock,1> tmp;
195 scoped_lock& s = *tmp.begin();
197 s.internal_release();
200 LeaveCriticalSection(&impl);
202 pthread_mutex_unlock(&impl);
203 #endif /* _WIN32||_WIN64 */
204 #endif /* TBB_USE_ASSERT */
207 //! Return native_handle
209 typedef LPCRITICAL_SECTION native_handle_type;
211 typedef pthread_mutex_t* native_handle_type;
213 native_handle_type native_handle() { return (native_handle_type) &impl; }
222 CRITICAL_SECTION impl;
225 pthread_mutex_t impl;
226 #endif /* _WIN32||_WIN64 */
228 //! All checks from mutex constructor using mutex.state were moved here
229 void __TBB_EXPORTED_METHOD internal_construct();
231 //! All checks from mutex destructor using mutex.state were moved here
232 void __TBB_EXPORTED_METHOD internal_destroy();
236 //! Set the internal state
237 void set_state( state_t to ) { state = to; }
241 __TBB_DEFINE_PROFILING_SET_NAME(mutex)
245 #endif /* __TBB_mutex_H */