blob: 3d4780ea10856aa4555a6aabb562b70d87090672 (
plain) (
blame)
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
#include "datetime.h"
#include "defaults.h"
#include <cstdio>
#include "atomic.h"
#include "event.h"
#include "mutex.h"
#include "condvar.h"
#ifdef _win_
#include "winint.h"
#endif
class TSystemEvent::TEvImpl: public TAtomicRefCount<TSystemEvent::TEvImpl> {
public:
#ifdef _win_
inline TEvImpl(ResetMode rmode) {
cond = CreateEvent(nullptr, rmode == rManual ? true : false, false, nullptr);
}
inline ~TEvImpl() {
CloseHandle(cond);
}
inline void Reset() noexcept {
ResetEvent(cond);
}
inline void Signal() noexcept {
SetEvent(cond);
}
inline bool WaitD(TInstant deadLine) noexcept {
if (deadLine == TInstant::Max()) {
return WaitForSingleObject(cond, INFINITE) == WAIT_OBJECT_0;
}
const TInstant now = Now();
if (now < deadLine) {
//TODO
return WaitForSingleObject(cond, (deadLine - now).MilliSeconds()) == WAIT_OBJECT_0;
}
return (WaitForSingleObject(cond, 0) == WAIT_OBJECT_0);
}
#else
inline TEvImpl(ResetMode rmode)
: Manual(rmode == rManual ? true : false)
{
}
inline void Signal() noexcept {
if (Manual && AtomicGet(Signaled)) {
return; // shortcut
}
with_lock (Mutex) {
AtomicSet(Signaled, 1);
}
if (Manual) {
Cond.BroadCast();
} else {
Cond.Signal();
}
}
inline void Reset() noexcept {
AtomicSet(Signaled, 0);
}
inline bool WaitD(TInstant deadLine) noexcept {
if (Manual && AtomicGet(Signaled)) {
return true; // shortcut
}
bool resSignaled = true;
with_lock (Mutex) {
while (!AtomicGet(Signaled)) {
if (!Cond.WaitD(Mutex, deadLine)) {
resSignaled = AtomicGet(Signaled); // timed out, but Signaled could have been set
break;
}
}
if (!Manual) {
AtomicSet(Signaled, 0);
}
}
return resSignaled;
}
#endif
private:
#ifdef _win_
HANDLE cond;
#else
TCondVar Cond;
TMutex Mutex;
TAtomic Signaled = 0;
bool Manual;
#endif
};
TSystemEvent::TSystemEvent(ResetMode rmode)
: EvImpl_(new TEvImpl(rmode))
{
}
TSystemEvent::TSystemEvent(const TSystemEvent& other) noexcept
: EvImpl_(other.EvImpl_)
{
}
TSystemEvent& TSystemEvent::operator=(const TSystemEvent& other) noexcept {
EvImpl_ = other.EvImpl_;
return *this;
}
TSystemEvent::~TSystemEvent() = default;
void TSystemEvent::Reset() noexcept {
EvImpl_->Reset();
}
void TSystemEvent::Signal() noexcept {
EvImpl_->Signal();
}
bool TSystemEvent::WaitD(TInstant deadLine) noexcept {
return EvImpl_->WaitD(deadLine);
}
|