-
Notifications
You must be signed in to change notification settings - Fork 1
/
EventLoop.cpp
183 lines (147 loc) · 4.35 KB
/
EventLoop.cpp
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include "EventLoop.h"
class Channel;
int createtimerfd(int sec=10)
{
// 把定时器加入epoll。
int tfd=timerfd_create(CLOCK_MONOTONIC,TFD_CLOEXEC|TFD_NONBLOCK); // 创建timerfd。
struct itimerspec timeout; // 定时时间的数据结构。
memset(&timeout,0,sizeof(struct itimerspec));
timeout.it_value.tv_sec = sec; // 定时时间为5秒。
timeout.it_value.tv_nsec = 0;
timerfd_settime(tfd,0,&timeout,0); // 开始计时。alarm(5)
return tfd;
}
EventLoop::EventLoop(bool mainloop, int timetvl, int timeout)
:ep_(new Epoll),wakeupfd_(eventfd(0,EFD_NONBLOCK)),
stop_(false),
mainloop_(mainloop),
wakechannel_(new Channel(this,wakeupfd_)),
timerfd_(createtimerfd(timetvl)),timerchannel_(new Channel(this,timerfd_)),
timetvl_(timetvl),timeout_(timeout)
{
wakechannel_->setreadcallback(std::bind(&EventLoop::handlewakeup,this));
wakechannel_->enablereading();
timerchannel_->setreadcallback(std::bind(&EventLoop::handletimer,this));
timerchannel_->enablereading();
}
EventLoop::~EventLoop()
{
// delete ep_;
}
void EventLoop::stop()
{
stop_=true;
wakeup();
}
void EventLoop::run()
{
threadid_ = syscall(SYS_gettid);
while (stop_==false) // 事件循环。
{
std::vector <Channel *> channels = ep_->loop(10*1000); //等待事件发生 成功发生事件 push到vector容器的尾部
//为空时是因为执行了ep_->loop中的epoll_wait()超时了 返回了空的channel
if(channels.size() == 0)
{
epolltimeoutcallback_(this);
}
else
{
for(auto &ch:channels)
{
ch->handleevent();
}
}
}
}
// std::unique_ptr<Epoll> EventLoop::ep()
// {
// return ep_;
// }
void EventLoop::wakeup()
{
uint64_t val = 1;
write(wakeupfd_,&val,sizeof(uint64_t));
}
void EventLoop::queueinloop(std::function<void()> fn)
{
{
std::lock_guard<std::mutex> gd(mutex_);
taskqueue_.push(fn);
}
//唤醒事件循环
wakeup();
}
void EventLoop::handlewakeup()
{
uint64_t val;
read(wakeupfd_, &val, sizeof(uint64_t)); //从eventfd中读取数据出来,如果不读取, 在水平触发的模式下eventfd的读事件会一直触发
std::function<void()> fn;
std::lock_guard<std::mutex> gd(mutex_); //给任务队列加锁
while(taskqueue_.size() >0)
{
fn = std::move(taskqueue_.front());
taskqueue_.pop();
fn();
}
}
bool EventLoop::isinloopthread()
{
return threadid_ == syscall(SYS_gettid);
}
void EventLoop::updateChannel(Channel *ch)
{
ep_->updateChannel(ch);
}
void EventLoop::removeChannel(Channel *ch)
{
ep_->removeChannel(ch);
}
void EventLoop::setepolltimeoutcallback(std::function<void(EventLoop*)> fn)
{
epolltimeoutcallback_ = fn;
}
void EventLoop::handletimer()
{
struct itimerspec timeout; // 定时时间的数据结构。
memset(&timeout,0,sizeof(struct itimerspec));
timeout.it_value.tv_sec = timetvl_; // 定时时间为5秒。
timeout.it_value.tv_nsec = 0;
timerfd_settime(timerfd_,0,&timeout,0); // 开始计时。alarm(5)
if(mainloop_)
{
}
else
{
time_t now = time(0); //获取当前时间
// if (conns_.size() <=0)
// {
// printf("conns_.size()=%ld\n",conns_.size());
// return;
// }
for(auto cc=conns_.begin();cc!=conns_.end();)
{
if(cc->first <= 0)
{
continue;
}
// printf("cc=%d-type=%s-thread=%ld,", cc->first, typeid(cc->first).name(),syscall(SYS_gettid));
if(cc->second->timeout(now, timeout_))
{
timercallback_(cc->first);
std::lock_guard<std::mutex> gd(mmutex_);
cc = conns_.erase(cc); //从map中删除 超时的conn
} else cc++;
}
}
}
void EventLoop::newconnection(spConnection conn)
{
{
std::lock_guard<std::mutex> gd(mmutex_);
conns_[conn->fd()] = conn;
}
}
void EventLoop::settimercallback(std::function<void(int)> fn)
{
timercallback_ = fn;
}