-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathKEventLoop.cpp
More file actions
114 lines (100 loc) · 3.52 KB
/
Copy pathKEventLoop.cpp
File metadata and controls
114 lines (100 loc) · 3.52 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
#include "KEventLoop.h"
#include "KAsyncWaker.h"
#include "webserver/poller/KChannel.h"
#include "webserver/poller/KEventManager.h"
#include "webserver/utils/KAsyncLogger.h"
using namespace kback;
// 通过 __thread 来保证一个线程只能创建一个 EventLoop
// __thread 变量是每个线程有的一份独立的实体
// 类似于static 只在编译期初始化
thread_local EventLoop *t_loopInThisThread = nullptr;
const int kPollTimeMs = 1000;
EventLoop::EventLoop()
: looping_(false), threadId_(std::this_thread::get_id()),
eventmanager_(new EventManager(this)), quit_(false),
callingPendingFunctors_(false), asyncWaker_(new AsyncWaker(this)) {
KBACK_LOG_TRACE("EventLoop created %p in thread %zu", this,
std::hash<std::thread::id>{}(threadId_));
if (t_loopInThisThread) {
KBACK_LOG_FATAL("Another EventLoop %p exists in thread %zu",
t_loopInThisThread,
std::hash<std::thread::id>{}(threadId_));
} else {
t_loopInThisThread = this;
}
}
EventLoop::~EventLoop() {
assert(!looping_);
t_loopInThisThread = nullptr;
}
void EventLoop::loop() {
assert(!looping_);
assertInLoopThread();
looping_ = true;
quit_.store(false, std::memory_order_release);
while (!quit_.load(std::memory_order_acquire)) {
activeChannels_.clear();
// 这里poll在轮询中,为阻塞的,想要回调活动事件,必须想办法唤醒
// muduo这里采用了一个很巧妙的办法,专门用一个文件描述符来进行唤醒
pollReturnTime_ = eventmanager_->poll(kPollTimeMs, &activeChannels_);
for (auto it = activeChannels_.begin(); it != activeChannels_.end(); ++it) {
(*it)->handleEvent(pollReturnTime_);
}
doPendingFunctors();
}
KBACK_LOG_TRACE("EventLoop %p stop looping", this);
looping_ = false;
}
void EventLoop::quit() {
quit_.store(true, std::memory_order_release);
if (!isInLoopThread()) {
asyncWaker_->wakeup();
}
}
// channel 中注册了事件,需要更新,但是
// 为了保证线程安全,channel自己是不会更新的,
// 将更新的工作转交给loop, 然后在loop线程中 同步poll 中的channel
void EventLoop::updateChannel(Channel *channel) {
assert(channel->ownerLoop() == this);
assertInLoopThread();
// EventLoop 实际上不负责更新channel
eventmanager_->updateChannel(channel);
}
void EventLoop::removeChannel(Channel *channel) {
assert(channel->ownerLoop() == this);
assertInLoopThread();
eventmanager_->removeChannel(channel);
}
void EventLoop::abortNotInLoopThread() {
KBACK_LOG_FATAL(
"EventLoop::abortNotInLoopThread - EventLoop %p was created in "
"threadId_=%zu, current thread id=%zu",
this, std::hash<std::thread::id>{}(threadId_),
std::hash<std::thread::id>{}(std::this_thread::get_id()));
std::abort();
}
// 执行装载的的回调函数,下面的处理方法很巧妙
void EventLoop::doPendingFunctors() {
callingPendingFunctors_ = true;
pendingFunctors_.consumeAll([](Functor &functor) {
if (functor != nullptr) {
functor();
}
});
callingPendingFunctors_ = false;
}
// !这个函数是在loop启动之前调用的,用于设置channel
void EventLoop::runInLoop(Functor cb) {
if (isInLoopThread()) {
cb();
} else {
queueInLoop(std::move(cb));
}
}
// queueInLoop 是public的,不一定要被runInLoop调用,也可以被直接调用
void EventLoop::queueInLoop(Functor cb) {
pendingFunctors_.push(std::move(cb));
if (!isInLoopThread() || callingPendingFunctors_) {
asyncWaker_->wakeup();
}
}