25
25
#include < thread>
26
26
#include < assert.h>
27
27
#ifdef _WIN32
28
+ #include < windows.h>
28
29
#include < io.h>
30
+ #include < synchapi.h>
29
31
using ssize_t = long long ;
30
32
#else
31
33
#include < poll.h>
@@ -101,7 +103,7 @@ EventLoop::EventLoop()
101
103
void EventLoop::resetTimerQueue ()
102
104
{
103
105
assertInLoopThread ();
104
- assert (!looping_);
106
+ assert (!looping_. load (std::memory_order_acquire) );
105
107
timerQueue_->reset ();
106
108
}
107
109
#endif
@@ -111,8 +113,29 @@ void EventLoop::resetAfterFork()
111
113
}
112
114
EventLoop::~EventLoop ()
113
115
{
116
+ #ifdef _WIN32
117
+ DWORD delay = 1 ; /* 1 msec */
118
+ #else
119
+ struct timespec delay = {0 , 1000000 }; /* 1 msec */
120
+ #endif
121
+
114
122
quit ();
115
- assert (!looping_);
123
+
124
+ // Spin waiting for the loop to exit because
125
+ // this may take some time to complete. We
126
+ // assume the loop thread will *always* exit.
127
+ // If this cannot be guaranteed then one option
128
+ // might be to abort waiting and
129
+ // assert(!looping_) after some delay;
130
+ while (looping_.load (std::memory_order_acquire))
131
+ {
132
+ #ifdef _WIN32
133
+ Sleep (delay);
134
+ #else
135
+ nanosleep (&delay, nullptr );
136
+ #endif
137
+ }
138
+
116
139
t_loopInThisThread = nullptr ;
117
140
#ifdef __linux__
118
141
close (wakeupFd_);
@@ -140,7 +163,7 @@ void EventLoop::removeChannel(Channel *channel)
140
163
}
141
164
void EventLoop::quit ()
142
165
{
143
- quit_ = true ;
166
+ quit_. store ( true , std::memory_order_release) ;
144
167
145
168
Func f;
146
169
while (funcsOnQuit_.dequeue (f))
@@ -160,10 +183,10 @@ void EventLoop::loop()
160
183
{
161
184
assert (!looping_);
162
185
assertInLoopThread ();
163
- looping_ = true ;
164
- quit_ = false ;
186
+ looping_. store ( true , std::memory_order_release) ;
187
+ quit_. store ( false , std::memory_order_release) ;
165
188
166
- while (!quit_)
189
+ while (!quit_. load (std::memory_order_acquire) )
167
190
{
168
191
activeChannels_.clear ();
169
192
#ifdef __linux__
@@ -187,7 +210,7 @@ void EventLoop::loop()
187
210
// std::cout << "looping" << endl;
188
211
doRunInLoopFuncs ();
189
212
}
190
- looping_ = false ;
213
+ looping_. store ( false , std::memory_order_release) ;
191
214
}
192
215
void EventLoop::abortNotInLoopThread ()
193
216
{
@@ -198,15 +221,15 @@ void EventLoop::abortNotInLoopThread()
198
221
void EventLoop::queueInLoop (const Func &cb)
199
222
{
200
223
funcs_.enqueue (cb);
201
- if (!isInLoopThread () || !looping_)
224
+ if (!isInLoopThread () || !looping_. load (std::memory_order_acquire) )
202
225
{
203
226
wakeup ();
204
227
}
205
228
}
206
229
void EventLoop::queueInLoop (Func &&cb)
207
230
{
208
231
funcs_.enqueue (std::move (cb));
209
- if (!isInLoopThread () || !looping_)
232
+ if (!isInLoopThread () || !looping_. load (std::memory_order_acquire) )
210
233
{
211
234
wakeup ();
212
235
}
0 commit comments