-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsemaphore
115 lines (112 loc) · 4.4 KB
/
semaphore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//==============================================================================
// HackingSTL : semaphore
//
// https://github.com/metarutaiga/HackingSTL
//==============================================================================
#pragma once
#include <cstddef>
#if _LIBCPP_VERSION >= 11000 && !defined(__APPLE__)
# include_next <semaphore>
#elif _LIBCPP_VERSION || __GLIBCXX__
# if defined(__APPLE__)
# include <dispatch/dispatch.h>
# else
# include <semaphore.h>
# endif
# include <chrono>
# if defined(_LIBCPP_BEGIN_NAMESPACE_STD)
_LIBCPP_BEGIN_NAMESPACE_STD
# elif defined(_GLIBCXX_BEGIN_NAMESPACE_VERSION)
namespace std {
_GLIBCXX_BEGIN_NAMESPACE_VERSION
# else
namespace std {
# endif
template<ptrdiff_t LeastMaxValue = 0>
class counting_semaphore
{
# if defined(__APPLE__)
dispatch_semaphore_t __semaphore;
bool __wait_timed(struct timespec* __ts) { return dispatch_semaphore_wait(__semaphore, dispatch_walltime(__ts, 0)) == 0; }
public:
counting_semaphore(ptrdiff_t count = 0) { __semaphore = dispatch_semaphore_create(count); }
~counting_semaphore() { dispatch_release(__semaphore); }
void release(ptrdiff_t update = 1) { while(update--) dispatch_semaphore_signal(__semaphore); }
void acquire() { dispatch_semaphore_wait(__semaphore, DISPATCH_TIME_FOREVER); }
# else
sem_t __semaphore;
bool __wait_timed(struct timespec* __ts) { return sem_timedwait(&__semaphore, __ts) == 0; }
public:
counting_semaphore(ptrdiff_t count = 0) { sem_init(&__semaphore, 0, count); }
~counting_semaphore() { sem_destroy(&__semaphore); }
void release(ptrdiff_t update = 1) { while(update--) sem_post(&__semaphore); }
void acquire() { while(sem_wait(&__semaphore) == -1 && errno == EINTR); }
# endif
template<class Rep, class Period>
bool try_acquire_for(chrono::duration<Rep, Period> const& __rel_time)
{
chrono::nanoseconds __ns = chrono::system_clock::now().time_since_epoch() + chrono::duration_cast<chrono::nanoseconds>(__rel_time);
chrono::seconds __s = chrono::duration_cast<chrono::seconds>(__ns);
struct timespec __ts;
__ts.tv_sec = __s.count();
__ts.tv_nsec = (__ns - __s).count();
return __wait_timed(&__ts);
}
bool try_acquire()
{
return try_acquire_for(chrono::nanoseconds::zero());
}
template<class Clock, class Duration>
bool try_acquire_until(chrono::time_point<Clock, Duration> const& __abs_time)
{
auto const current = Clock::now();
if (current >= __abs_time)
return try_acquire();
else
return try_acquire_for(__abs_time - current);
}
};
# if defined(_LIBCPP_END_NAMESPACE_STD)
_LIBCPP_END_NAMESPACE_STD
# elif defined(_GLIBCXX_END_NAMESPACE_VERSION)
_GLIBCXX_END_NAMESPACE_VERSION
}
# else
}
# endif
#endif
#if _MSVC_STL_UPDATE
# include <WinBase.h>
# include <chrono>
_STD_BEGIN
template<ptrdiff_t LeastMaxValue = 0>
class counting_semaphore
{
HANDLE __semaphore;
public:
counting_semaphore(ptrdiff_t count = 0) { __semaphore = CreateSemaphoreA(nullptr, static_cast<LONG>(count), LONG_MAX, nullptr); }
~counting_semaphore() { CloseHandle(__semaphore); }
void release(ptrdiff_t update = 1) { ReleaseSemaphore(__semaphore, static_cast<LONG>(update), nullptr); }
void acquire() { WaitForSingleObject(__semaphore, INFINITE); }
template<class Rep, class Period>
bool try_acquire_for(chrono::duration<Rep, Period> const& __rel_time)
{
chrono::milliseconds __ms = chrono::duration_cast<chrono::milliseconds>(__rel_time);
return WaitForSingleObject(__semaphore, static_cast<DWORD>(__ms.count())) == WAIT_OBJECT_0;
}
bool try_acquire()
{
return try_acquire_for(chrono::nanoseconds::zero());
}
template<class Clock, class Duration>
bool try_acquire_until(chrono::time_point<Clock, Duration> const& __abs_time)
{
auto const current = Clock::now();
if (current >= __abs_time)
return try_acquire();
else
return try_acquire_for(__abs_time - current);
}
};
_STD_END
#endif