-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevent.cc
87 lines (71 loc) · 2.09 KB
/
event.cc
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
#include "event.h"
#include <time.h>
#include <errno.h>
namespace infra
{
namespace thread
{
Event::Event(bool signaled /* = false */)
: signal_(signaled),
reset_request_(false),
waiting_threads_(0),
mutex_(PTHREAD_MUTEX_INITIALIZER),
cond_(PTHREAD_COND_INITIALIZER) {
}
void Event::Wait() {
pthread_mutex_lock(&this->mutex_);
/// 这里记录等待的线程数是为了在有信号的时候所有的之前等待的线程都会收到信号
/// 之后才会复位。否则会发生其中的一个线程收到信号之后就复位了,其他等待的线程
/// 就没有收到信号,这不符合事件的语义。
++this->waiting_threads_;
while(!this->signal_) pthread_cond_wait(&this->cond_, &this->mutex_);
--this->waiting_threads_;
if(0 == this->waiting_threads_ && this->reset_request_) {
this->signal_ = false;
this->reset_request_ = false;
}
pthread_mutex_unlock(&this->mutex_);
}
bool Event::TimedWait(long timeout_ms) {
int what = 0;
pthread_mutex_lock(&this->mutex_);
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += timeout_ms / 1000;
ts.tv_nsec += (timeout_ms % 1000) * 1000 * 1000;
ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
ts.tv_nsec = ts.tv_nsec % (1000 * 1000 * 1000);
++this->waiting_threads_;
while(!this->signal_) {
what = pthread_cond_timedwait(&this->cond_, &this->mutex_, &ts);
if(ETIMEDOUT == what) break;
}
--this->waiting_threads_;
/// what == 0 表示已经有信号了。
if(0 == what &&
0 == this->waiting_threads_ &&
this->reset_request_) {
this->signal_ = false;
this->reset_request_ = false;
}
pthread_mutex_unlock(&this->mutex_);
return 0 == what;
}
void Event::Signal() {
pthread_mutex_lock(&this->mutex_);
this->signal_ = true;
pthread_cond_broadcast(&this->cond_);
pthread_mutex_unlock(&this->mutex_);
}
void Event::Reset() {
pthread_mutex_lock(&this->mutex_);
if(0 == this->waiting_threads_) {
this->signal_ = false;
this->reset_request_ = false;
} else {
this->reset_request_ = true;
}
pthread_mutex_unlock(&this->mutex_);
}
}
}