BRE12
recursive_mutex.h
1 /*
2  Copyright 2005-2016 Intel Corporation. All Rights Reserved.
3 
4  This file is part of Threading Building Blocks. Threading Building Blocks is free software;
5  you can redistribute it and/or modify it under the terms of the GNU General Public License
6  version 2 as published by the Free Software Foundation. Threading Building Blocks is
7  distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9  See the GNU General Public License for more details. You should have received a copy of
10  the GNU General Public License along with Threading Building Blocks; if not, write to the
11  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12 
13  As a special exception, you may use this file as part of a free software library without
14  restriction. Specifically, if other files instantiate templates or use macros or inline
15  functions from this file, or you compile this file and link it with other files to produce
16  an executable, this file does not by itself cause the resulting executable to be covered
17  by the GNU General Public License. This exception does not however invalidate any other
18  reasons why the executable file might be covered by the GNU General Public License.
19 */
20 
21 #ifndef __TBB_recursive_mutex_H
22 #define __TBB_recursive_mutex_H
23 
24 #if _WIN32||_WIN64
25 #include "machine/windows_api.h"
26 #else
27 #include <pthread.h>
28 #endif /* _WIN32||_WIN64 */
29 
30 #include <new>
31 #include "aligned_space.h"
32 #include "tbb_stddef.h"
33 #include "tbb_profiling.h"
34 
35 namespace tbb {
37 
39 class recursive_mutex : internal::mutex_copy_deprecated_and_disabled {
40 public:
43 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
44  internal_construct();
45 #else
46  #if _WIN32||_WIN64
47  InitializeCriticalSectionEx(&impl, 4000, 0);
48  #else
49  pthread_mutexattr_t mtx_attr;
50  int error_code = pthread_mutexattr_init( &mtx_attr );
51  if( error_code )
52  tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutexattr_init failed");
53 
54  pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE );
55  error_code = pthread_mutex_init( &impl, &mtx_attr );
56  if( error_code )
57  tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_init failed");
58 
59  pthread_mutexattr_destroy( &mtx_attr );
60  #endif /* _WIN32||_WIN64*/
61 #endif /* TBB_USE_ASSERT */
62  };
63 
64  ~recursive_mutex() {
65 #if TBB_USE_ASSERT
66  internal_destroy();
67 #else
68  #if _WIN32||_WIN64
69  DeleteCriticalSection(&impl);
70  #else
71  pthread_mutex_destroy(&impl);
72 
73  #endif /* _WIN32||_WIN64 */
74 #endif /* TBB_USE_ASSERT */
75  };
76 
77  class scoped_lock;
78  friend class scoped_lock;
79 
81 
83  class scoped_lock: internal::no_copy {
84  public:
86  scoped_lock() : my_mutex(NULL) {};
87 
90 #if TBB_USE_ASSERT
91  my_mutex = &mutex;
92 #endif /* TBB_USE_ASSERT */
93  acquire( mutex );
94  }
95 
98  if( my_mutex )
99  release();
100  }
101 
104 #if TBB_USE_ASSERT
105  internal_acquire( mutex );
106 #else
107  my_mutex = &mutex;
108  mutex.lock();
109 #endif /* TBB_USE_ASSERT */
110  }
111 
114 #if TBB_USE_ASSERT
115  return internal_try_acquire( mutex );
116 #else
117  bool result = mutex.try_lock();
118  if( result )
119  my_mutex = &mutex;
120  return result;
121 #endif /* TBB_USE_ASSERT */
122  }
123 
125  void release() {
126 #if TBB_USE_ASSERT
127  internal_release();
128 #else
129  my_mutex->unlock();
130  my_mutex = NULL;
131 #endif /* TBB_USE_ASSERT */
132  }
133 
134  private:
136  recursive_mutex* my_mutex;
137 
139  void __TBB_EXPORTED_METHOD internal_acquire( recursive_mutex& m );
140 
142  bool __TBB_EXPORTED_METHOD internal_try_acquire( recursive_mutex& m );
143 
145  void __TBB_EXPORTED_METHOD internal_release();
146 
147  friend class recursive_mutex;
148  };
149 
150  // Mutex traits
151  static const bool is_rw_mutex = false;
152  static const bool is_recursive_mutex = true;
153  static const bool is_fair_mutex = false;
154 
155  // C++0x compatibility interface
156 
158  void lock() {
159 #if TBB_USE_ASSERT
161  new(tmp.begin()) scoped_lock(*this);
162 #else
163  #if _WIN32||_WIN64
164  EnterCriticalSection(&impl);
165  #else
166  int error_code = pthread_mutex_lock(&impl);
167  if( error_code )
168  tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_lock failed");
169  #endif /* _WIN32||_WIN64 */
170 #endif /* TBB_USE_ASSERT */
171  }
172 
174 
175  bool try_lock() {
176 #if TBB_USE_ASSERT
178  return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this);
179 #else
180  #if _WIN32||_WIN64
181  return TryEnterCriticalSection(&impl)!=0;
182  #else
183  return pthread_mutex_trylock(&impl)==0;
184  #endif /* _WIN32||_WIN64 */
185 #endif /* TBB_USE_ASSERT */
186  }
187 
189  void unlock() {
190 #if TBB_USE_ASSERT
192  scoped_lock& s = *tmp.begin();
193  s.my_mutex = this;
194  s.internal_release();
195 #else
196  #if _WIN32||_WIN64
197  LeaveCriticalSection(&impl);
198  #else
199  pthread_mutex_unlock(&impl);
200  #endif /* _WIN32||_WIN64 */
201 #endif /* TBB_USE_ASSERT */
202  }
203 
205  #if _WIN32||_WIN64
206  typedef LPCRITICAL_SECTION native_handle_type;
207  #else
208  typedef pthread_mutex_t* native_handle_type;
209  #endif
210  native_handle_type native_handle() { return (native_handle_type) &impl; }
211 
212 private:
213 #if _WIN32||_WIN64
214  CRITICAL_SECTION impl;
215  enum state_t {
216  INITIALIZED=0x1234,
217  DESTROYED=0x789A,
218  } state;
219 #else
220  pthread_mutex_t impl;
221 #endif /* _WIN32||_WIN64 */
222 
224  void __TBB_EXPORTED_METHOD internal_construct();
225 
227  void __TBB_EXPORTED_METHOD internal_destroy();
228 };
229 
230 __TBB_DEFINE_PROFILING_SET_NAME(recursive_mutex)
231 
232 } // namespace tbb
233 
234 #endif /* __TBB_recursive_mutex_H */
pthread_mutex_t * native_handle_type
Return native_handle.
Definition: recursive_mutex.h:208
void unlock()
Release lock.
Definition: recursive_mutex.h:189
recursive_mutex()
Construct unacquired recursive_mutex.
Definition: recursive_mutex.h:42
Block of space aligned sufficiently to construct an array T with N elements.
Definition: aligned_space.h:33
void acquire(recursive_mutex &mutex)
Acquire lock on given mutex.
Definition: recursive_mutex.h:103
scoped_lock()
Construct lock that has not acquired a recursive_mutex.
Definition: recursive_mutex.h:86
Mutex that allows recursive mutex acquisition.
Definition: recursive_mutex.h:39
scoped_lock(recursive_mutex &mutex)
Acquire lock on given mutex.
Definition: recursive_mutex.h:89
T * begin()
Pointer to beginning of array.
Definition: aligned_space.h:39
The namespace tbb contains all components of the library.
Definition: parallel_for.h:44
bool try_acquire(recursive_mutex &mutex)
Try acquire lock on given recursive_mutex.
Definition: recursive_mutex.h:113
The scoped locking pattern.
Definition: recursive_mutex.h:83
~scoped_lock()
Release lock (if lock is held).
Definition: recursive_mutex.h:97
Wrapper around the platform&#39;s native reader-writer lock.
Definition: mutex.h:40
bool try_lock()
Try acquiring lock (non-blocking)
Definition: recursive_mutex.h:175
void release()
Release lock.
Definition: recursive_mutex.h:125
void lock()
Acquire lock.
Definition: recursive_mutex.h:158