-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEventLoop.cpp
More file actions
181 lines (161 loc) · 4.49 KB
/
Copy pathEventLoop.cpp
File metadata and controls
181 lines (161 loc) · 4.49 KB
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
#include "EventLoop.h"
#include "Logger.h"
#include "Poller.h"
#include "Channel.h"
#include <sys/eventfd.h>
#include <unistd.h>
#include <fcntl.h>
// 防止一个线程创建多个EventLoop
__thread EventLoop* t_loopInThisThread = nullptr;
// 定义默认Poller的IO复用接口的超时时间
const int kPollTime = 10000;
// 创建wakeupfd,用于唤醒subreactor处理新来的channel
int createEventfd()
{
int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
if (evtfd < 0)
{
LOG_FATAL("Unable to create eventfd:%d \n", errno);
}
return evtfd;
}
EventLoop::EventLoop()
: looping_(false)
, quit_(false)
, callingPendingFunctors_(false)
, threadId_(CurrentThread::tid())
, poller_(Poller::newDefaultPoller(this))
, wakeupfd_(createEventfd())
, wakeupChannel_(new Channel(this, wakeupfd_))
, currentActiveChannel_(nullptr)
{
LOG_DEBUG("EventLoop created %p in thread %d \n", this, threadId_);
if (t_loopInThisThread)
{
LOG_FATAL("Another EventLoop %p exists in this thread %d \n", this, threadId_);
}
else
{
t_loopInThisThread = this;
}
// 设置wakeupfd的事件类型以及发生事件后的回调操作
wakeupChannel_->setReadEventCallback(std::bind(&EventLoop::handleRead, this));
// 每一个EventLoop都将监听wakeupChannel的EPOLLIN事件
wakeupChannel_->enableReading();
}
EventLoop::~EventLoop()
{
wakeupChannel_->disableAll();
wakeupChannel_->remove();
::close(wakeupfd_);
t_loopInThisThread = nullptr;
}
void EventLoop::loop()
{
looping_ = true;
quit_ = false;
LOG_INFO("EventLoop %p start looping \n", this);
while (!quit_)
{
activeChannels_.clear();
// 监听两类fd,一种是client的fd,一种是wakeup的fd
pollReturnTime_ = poller_->poll(kPollTime, &activeChannels_);
for (Channel* channel : activeChannels_)
{
currentActiveChannel_ = channel;
currentActiveChannel_->handleEvent(pollReturnTime_);
}
// 执行当前EventLoop需要处理的回调操作
/**
* IO线程mainloop主要做accept的工作,将已连接的fd分配给subloop
* mainLoop事先注册一个回调,需要subloop执行,即通过wakeup唤醒subloop
* subloop执行mainloop注册的回调函数,即下面的方法
*/
doPendingFunctors();
}
LOG_INFO("EventLoop %p stop looping. \n", this);
looping_ = false;
}
/**
* 退出的两种情况:
* 1. loop在自己的线程中调用
* 2. loop被其他线程调用
*/
void EventLoop::quit()
{
quit_ = true;
// 确保能够正确退出,wakeup退出poll轮询
if (!isInLoopThread())
{
wakeup();
}
}
void EventLoop::runInLoop(Functor cb)
{
if (isInLoopThread())
{
cb();
}
else // 在非当前loop线程中调用cb, 就需要唤醒loop所在的线程执行cb
{
queueInLoop(std::move(cb));
}
}
void EventLoop::queueInLoop(Functor cb)
{
{
std::unique_lock<std::mutex> lock(mutex_);
pendingFunctors_.emplace_back(cb);
}
// 唤醒相应的,需要执行上面回调操作的loop的线程
// 在上一轮回调还在执行时,就进行唤醒操作
if (!isInLoopThread() || callingPendingFunctors_)
{
wakeup(); // 唤醒loop所在线程
}
}
// wakeup向wakeupfd写一个数据,wakeupchannel发生读事件,subloop会被唤醒
void EventLoop::wakeup()
{
uint64_t one = 1;
ssize_t n = write(wakeupfd_, &one, sizeof(one));
if (n != sizeof(one))
{
LOG_ERROR("EventLoop::wakeup() writes %lu bytes instead of 8", n);
}
}
void EventLoop::handleRead()
{
uint64_t one = 1;
ssize_t n = read(wakeupfd_, &one, sizeof(one));
if (n!=sizeof(one))
{
LOG_ERROR("EventLoop::handleRead() reads %lu bytes instead of 8 \n", n);
}
}
void EventLoop::removeChannel(Channel* channel)
{
poller_->removeChannel(channel);
}
void EventLoop::updateChannel(Channel* channel)
{
poller_->updateChannel(channel);
}
bool EventLoop::hasChannel(Channel* channel)
{
return poller_->hasChannel(channel);
}
void EventLoop::doPendingFunctors()
{
std::vector<Functor> functors;
callingPendingFunctors_ = true;
{
std::unique_lock<std::mutex> lock(mutex_);
functors.swap(pendingFunctors_);
}
for (const Functor& functor : functors)
{
functor(); // 执行当前loop需要执行的回调操作
}
callingPendingFunctors_ = false;
}