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-2020 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#ifndef __TBB_tbb_semaphore_H
18#define __TBB_tbb_semaphore_H
19
20#include <tbb/atomic.h>
21#include "tbb/tbb_stddef.h"
22
23#if _WIN32||_WIN64
25
26#elif __APPLE__
27#include <mach/semaphore.h>
28#include <mach/task.h>
29#include <mach/mach_init.h>
30#include <mach/error.h>
31
32#else
33#include <semaphore.h>
34#ifdef TBB_USE_DEBUG
35#include <errno.h>
36#endif
37#endif /*_WIN32||_WIN64*/
38
39namespace tbb {
40namespace internal {
41
42
43#if _WIN32||_WIN64
44typedef LONG sem_count_t;
46class semaphore : no_copy {
47 static const int max_semaphore_cnt = MAXLONG;
48public:
50 semaphore(size_t start_cnt_ = 0) {init_semaphore(start_cnt_);}
52 ~semaphore() {CloseHandle( sem );}
54 void P() {WaitForSingleObjectEx( sem, INFINITE, FALSE );}
56 void V() {ReleaseSemaphore( sem, 1, NULL );}
57private:
58 HANDLE sem;
59 void init_semaphore(size_t start_cnt_) {
60 sem = CreateSemaphoreEx( NULL, LONG(start_cnt_), max_semaphore_cnt, NULL, 0, SEMAPHORE_ALL_ACCESS );
61 }
62};
63#elif __APPLE__
65class semaphore : no_copy {
66public:
68 semaphore(int start_cnt_ = 0) : sem(start_cnt_) { init_semaphore(start_cnt_); }
70 ~semaphore() {
71 kern_return_t ret = semaphore_destroy( mach_task_self(), sem );
72 __TBB_ASSERT_EX( ret==err_none, NULL );
73 }
75 void P() {
76 int ret;
77 do {
78 ret = semaphore_wait( sem );
79 } while( ret==KERN_ABORTED );
80 __TBB_ASSERT( ret==KERN_SUCCESS, "semaphore_wait() failed" );
81 }
83 void V() { semaphore_signal( sem ); }
84private:
85 semaphore_t sem;
86 void init_semaphore(int start_cnt_) {
87 kern_return_t ret = semaphore_create( mach_task_self(), &sem, SYNC_POLICY_FIFO, start_cnt_ );
88 __TBB_ASSERT_EX( ret==err_none, "failed to create a semaphore" );
89 }
90};
91#else /* Linux/Unix */
92typedef uint32_t sem_count_t;
95public:
97 semaphore(int start_cnt_ = 0 ) { init_semaphore( start_cnt_ ); }
98
101 int ret = sem_destroy( &sem );
102 __TBB_ASSERT_EX( !ret, NULL );
103 }
105 void P() {
106 while( sem_wait( &sem )!=0 )
107 __TBB_ASSERT( errno==EINTR, NULL );
108 }
110 void V() { sem_post( &sem ); }
111private:
112 sem_t sem;
113 void init_semaphore(int start_cnt_) {
114 int ret = sem_init( &sem, /*shared among threads*/ 0, start_cnt_ );
115 __TBB_ASSERT_EX( !ret, NULL );
116 }
117};
118#endif /* _WIN32||_WIN64 */
119
120
122#if _WIN32||_WIN64
123#if !__TBB_USE_SRWLOCK
126public:
128 binary_semaphore() { my_sem = CreateEventEx( NULL, NULL, 0, EVENT_ALL_ACCESS ); }
130 ~binary_semaphore() { CloseHandle( my_sem ); }
132 void P() { WaitForSingleObjectEx( my_sem, INFINITE, FALSE ); }
134 void V() { SetEvent( my_sem ); }
135private:
136 HANDLE my_sem;
137};
138#else /* __TBB_USE_SRWLOCK */
139
140union srwl_or_handle {
141 SRWLOCK lock;
142 HANDLE h;
143};
144
146class binary_semaphore : no_copy {
147public:
153 void P();
155 void V();
156private:
157 srwl_or_handle my_sem;
158};
159#endif /* !__TBB_USE_SRWLOCK */
160#elif __APPLE__
162class binary_semaphore : no_copy {
163public:
165 binary_semaphore() : my_sem(0) {
166 kern_return_t ret = semaphore_create( mach_task_self(), &my_sem, SYNC_POLICY_FIFO, 0 );
167 __TBB_ASSERT_EX( ret==err_none, "failed to create a semaphore" );
168 }
171 kern_return_t ret = semaphore_destroy( mach_task_self(), my_sem );
172 __TBB_ASSERT_EX( ret==err_none, NULL );
173 }
175 void P() {
176 int ret;
177 do {
178 ret = semaphore_wait( my_sem );
179 } while( ret==KERN_ABORTED );
180 __TBB_ASSERT( ret==KERN_SUCCESS, "semaphore_wait() failed" );
181 }
183 void V() { semaphore_signal( my_sem ); }
184private:
185 semaphore_t my_sem;
186};
187#else /* Linux/Unix */
188
189#if __TBB_USE_FUTEX
190class binary_semaphore : no_copy {
191// The implementation is equivalent to the "Mutex, Take 3" one
192// in the paper "Futexes Are Tricky" by Ulrich Drepper
193public:
195 binary_semaphore() { my_sem = 1; }
199 void P() {
200 int s;
201 if( (s = my_sem.compare_and_swap( 1, 0 ))!=0 ) {
202 if( s!=2 )
203 s = my_sem.fetch_and_store( 2 );
204 while( s!=0 ) { // This loop deals with spurious wakeup
205 futex_wait( &my_sem, 2 );
206 s = my_sem.fetch_and_store( 2 );
207 }
208 }
209 }
211 void V() {
212 __TBB_ASSERT( my_sem>=1, "multiple V()'s in a row?" );
213 if( my_sem.fetch_and_store( 0 )==2 )
214 futex_wakeup_one( &my_sem );
215 }
216private:
217 atomic<int> my_sem; // 0 - open; 1 - closed, no waits; 2 - closed, possible waits
218};
219#else
220typedef uint32_t sem_count_t;
223public:
226 int ret = sem_init( &my_sem, /*shared among threads*/ 0, 0 );
227 __TBB_ASSERT_EX( !ret, NULL );
228 }
231 int ret = sem_destroy( &my_sem );
232 __TBB_ASSERT_EX( !ret, NULL );
233 }
235 void P() {
236 while( sem_wait( &my_sem )!=0 )
237 __TBB_ASSERT( errno==EINTR, NULL );
238 }
240 void V() { sem_post( &my_sem ); }
241private:
242 sem_t my_sem;
243};
244#endif /* __TBB_USE_FUTEX */
245#endif /* _WIN32||_WIN64 */
246
247} // namespace internal
248} // namespace tbb
249
250#endif /* __TBB_tbb_semaphore_H */
#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:167
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
void const char const char int ITT_FORMAT __itt_group_sync s
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
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
The graph class.
uint32_t sem_count_t
for performance reasons, we want specialized binary_semaphore
Definition: semaphore.h:92
Base class for types that should not be copied or assigned.
Definition: tbb_stddef.h:330
Edsger Dijkstra's counting semaphore.
Definition: semaphore.h:94
semaphore(int start_cnt_=0)
ctor
Definition: semaphore.h:97
void P()
wait/acquire
Definition: semaphore.h:105
void V()
post/release
Definition: semaphore.h:110
void init_semaphore(int start_cnt_)
Definition: semaphore.h:113
binary_semaphore for concurrent monitor
Definition: semaphore.h:222

Copyright © 2005-2020 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.