Intel(R) Threading Building Blocks Doxygen Documentation  version 4.2.3
semaphore.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2005-2019 Intel Corporation
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 
16 
17 
18 
19 */
20 
21 #ifndef __TBB_tbb_semaphore_H
22 #define __TBB_tbb_semaphore_H
23 
24 #include <tbb/atomic.h>
25 #include "tbb/tbb_stddef.h"
26 
27 #if _WIN32||_WIN64
29 
30 #elif __APPLE__
31 #include <mach/semaphore.h>
32 #include <mach/task.h>
33 #include <mach/mach_init.h>
34 #include <mach/error.h>
35 
36 #else
37 #include <semaphore.h>
38 #ifdef TBB_USE_DEBUG
39 #include <errno.h>
40 #endif
41 #endif /*_WIN32||_WIN64*/
42 
43 namespace tbb {
44 namespace internal {
45 
46 
47 #if _WIN32||_WIN64
48 typedef LONG sem_count_t;
50 class semaphore : no_copy {
51  static const int max_semaphore_cnt = MAXLONG;
52 public:
54  semaphore(size_t start_cnt_ = 0) {init_semaphore(start_cnt_);}
56  ~semaphore() {CloseHandle( sem );}
58  void P() {WaitForSingleObjectEx( sem, INFINITE, FALSE );}
60  void V() {ReleaseSemaphore( sem, 1, NULL );}
61 private:
62  HANDLE sem;
63  void init_semaphore(size_t start_cnt_) {
64  sem = CreateSemaphoreEx( NULL, LONG(start_cnt_), max_semaphore_cnt, NULL, 0, SEMAPHORE_ALL_ACCESS );
65  }
66 };
67 #elif __APPLE__
68 class semaphore : no_copy {
70 public:
72  semaphore(int start_cnt_ = 0) : sem(start_cnt_) { init_semaphore(start_cnt_); }
74  ~semaphore() {
75  kern_return_t ret = semaphore_destroy( mach_task_self(), sem );
76  __TBB_ASSERT_EX( ret==err_none, NULL );
77  }
79  void P() {
80  int ret;
81  do {
82  ret = semaphore_wait( sem );
83  } while( ret==KERN_ABORTED );
84  __TBB_ASSERT( ret==KERN_SUCCESS, "semaphore_wait() failed" );
85  }
87  void V() { semaphore_signal( sem ); }
88 private:
89  semaphore_t sem;
90  void init_semaphore(int start_cnt_) {
91  kern_return_t ret = semaphore_create( mach_task_self(), &sem, SYNC_POLICY_FIFO, start_cnt_ );
92  __TBB_ASSERT_EX( ret==err_none, "failed to create a semaphore" );
93  }
94 };
95 #else /* Linux/Unix */
96 typedef uint32_t sem_count_t;
98 class semaphore : no_copy {
99 public:
101  semaphore(int start_cnt_ = 0 ) { init_semaphore( start_cnt_ ); }
102 
105  int ret = sem_destroy( &sem );
106  __TBB_ASSERT_EX( !ret, NULL );
107  }
109  void P() {
110  while( sem_wait( &sem )!=0 )
111  __TBB_ASSERT( errno==EINTR, NULL );
112  }
114  void V() { sem_post( &sem ); }
115 private:
116  sem_t sem;
117  void init_semaphore(int start_cnt_) {
118  int ret = sem_init( &sem, /*shared among threads*/ 0, start_cnt_ );
119  __TBB_ASSERT_EX( !ret, NULL );
120  }
121 };
122 #endif /* _WIN32||_WIN64 */
123 
124 
126 #if _WIN32||_WIN64
127 #if !__TBB_USE_SRWLOCK
128 class binary_semaphore : no_copy {
130 public:
132  binary_semaphore() { my_sem = CreateEventEx( NULL, NULL, 0, EVENT_ALL_ACCESS ); }
134  ~binary_semaphore() { CloseHandle( my_sem ); }
136  void P() { WaitForSingleObjectEx( my_sem, INFINITE, FALSE ); }
138  void V() { SetEvent( my_sem ); }
139 private:
140  HANDLE my_sem;
141 };
142 #else /* __TBB_USE_SRWLOCK */
143 
144 union srwl_or_handle {
145  SRWLOCK lock;
146  HANDLE h;
147 };
148 
150 class binary_semaphore : no_copy {
151 public:
157  void P();
159  void V();
160 private:
161  srwl_or_handle my_sem;
162 };
163 #endif /* !__TBB_USE_SRWLOCK */
164 #elif __APPLE__
165 class binary_semaphore : no_copy {
167 public:
169  binary_semaphore() : my_sem(0) {
170  kern_return_t ret = semaphore_create( mach_task_self(), &my_sem, SYNC_POLICY_FIFO, 0 );
171  __TBB_ASSERT_EX( ret==err_none, "failed to create a semaphore" );
172  }
175  kern_return_t ret = semaphore_destroy( mach_task_self(), my_sem );
176  __TBB_ASSERT_EX( ret==err_none, NULL );
177  }
179  void P() {
180  int ret;
181  do {
182  ret = semaphore_wait( my_sem );
183  } while( ret==KERN_ABORTED );
184  __TBB_ASSERT( ret==KERN_SUCCESS, "semaphore_wait() failed" );
185  }
187  void V() { semaphore_signal( my_sem ); }
188 private:
189  semaphore_t my_sem;
190 };
191 #else /* Linux/Unix */
192 
193 #if __TBB_USE_FUTEX
194 class binary_semaphore : no_copy {
195 // The implementation is equivalent to the "Mutex, Take 3" one
196 // in the paper "Futexes Are Tricky" by Ulrich Drepper
197 public:
199  binary_semaphore() { my_sem = 1; }
201  ~binary_semaphore() {}
203  void P() {
204  int s;
205  if( (s = my_sem.compare_and_swap( 1, 0 ))!=0 ) {
206  if( s!=2 )
207  s = my_sem.fetch_and_store( 2 );
208  while( s!=0 ) { // This loop deals with spurious wakeup
209  futex_wait( &my_sem, 2 );
210  s = my_sem.fetch_and_store( 2 );
211  }
212  }
213  }
215  void V() {
216  __TBB_ASSERT( my_sem>=1, "multiple V()'s in a row?" );
217  if( my_sem.fetch_and_store( 0 )==2 )
218  futex_wakeup_one( &my_sem );
219  }
220 private:
221  atomic<int> my_sem; // 0 - open; 1 - closed, no waits; 2 - closed, possible waits
222 };
223 #else
224 typedef uint32_t sem_count_t;
227 public:
230  int ret = sem_init( &my_sem, /*shared among threads*/ 0, 0 );
231  __TBB_ASSERT_EX( !ret, NULL );
232  }
235  int ret = sem_destroy( &my_sem );
236  __TBB_ASSERT_EX( !ret, NULL );
237  }
239  void P() {
240  while( sem_wait( &my_sem )!=0 )
241  __TBB_ASSERT( errno==EINTR, NULL );
242  }
244  void V() { sem_post( &my_sem ); }
245 private:
246  sem_t my_sem;
247 };
248 #endif /* __TBB_USE_FUTEX */
249 #endif /* _WIN32||_WIN64 */
250 
251 } // namespace internal
252 } // namespace tbb
253 
254 #endif /* __TBB_tbb_semaphore_H */
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function h
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void P()
wait/acquire
Definition: semaphore.h:109
Base class for types that should not be copied or assigned.
Definition: tbb_stddef.h:335
semaphore(int start_cnt_=0)
ctor
Definition: semaphore.h:101
#define __TBB_ASSERT_EX(predicate, comment)
"Extended" version is useful to suppress warnings if a variable is only used with an assert
Definition: tbb_stddef.h:171
binary_semaphore for concurrent monitor
Definition: semaphore.h:226
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void * lock
The graph class.
uint32_t sem_count_t
for performance reasons, we want specialized binary_semaphore
Definition: semaphore.h:96
void init_semaphore(int start_cnt_)
Definition: semaphore.h:117
void const char const char int ITT_FORMAT __itt_group_sync s
void V()
post/release
Definition: semaphore.h:114
Edsger Dijkstra's counting semaphore.
Definition: semaphore.h:98

Copyright © 2005-2019 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.