Kanon(四): Channel(事件分发器)

ChannelReactor模式中的事件分发器(Event Dispatcher),管理感兴趣的事件注册注销并根据触发的事件分发到对应的事件处理器上。

事件可以分为:

  • 读事件(Read event)
  • 写事件(Write event)
  • 错误事件(error event)
  • 关闭事件(close event)
1
2
3
4
void SetReadCallback(ReadEventCallback);
void SetWriteCallback(EventCallback);
void SetErrorCallback(EventCallback);
void SetCloseCallback(EventCallback);

但是实际上用户感兴趣的只有前两者,后两者由库设置事件处理器。
因此事件接口为:

1
2
3
4
5
6
7
8
void EnableReading();
void EnableWriting();
void DisableReading();
void DisableWriting();
void DisableAll();
bool IsReading();
bool IsWriting();
bool IsNoneEvent();

事件循环的第二阶段就是调用活跃Channel的HandleEvents()来处理各种事件,即根据触发的事件来进行分发:

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
void Channel::HandleEvents(TimeStamp receive_time) {
// ...

/*
* POLLHUP indicates the connection is closed in two direction
* i.e. The FIN has been received and sent
*
* If POLLIN is set, we can read until 0(FIN->EOF) and close connection
* Otherwise, close it here
*
* \see https://stackoverflow.com/questions/56177060/pollhup-vs-pollrdhup
*/
if ((revents_ & POLLHUP) && !(revents_ & POLLIN)) {
LOG_WARN << "fd = " << fd_ << " POLLHUP happened";

if (close_callback_) close_callback_();
}

/*
* To TCP, POLLERR typically indicates RST has been received or sent.
* - To server, it is maybe occurred when SO_LINGER is set and timeout is set to 0.
* (But to this library, we don't set it). In other case, receive RST segment when
* three hand-shake to avoid old duplicate connection(\see RFC 793)
* - To client, it is maybe occurred when connect to a nonexistent server or server is
* configured to SO_LINGER/0. If connect() return acceptable errno except EINPROGRESS,
* will close old socket and reconnect to server.
*
* Therefore, the error_callback_ just log error message of socket(see tcp_connection.cc) is ok.
*/
if (revents_ & (POLLERR | POLLNVAL)) {
if (revents_ & POLLNVAL) {
LOG_WARN << "fd = " << fd_ << " POLLNVAL(fd not open) happend";
}
if (error_callback_) error_callback_();
}

// When revents_ == POLLIN, process message except FIN or RST
// RDHUP indicates peer half-close in write direction(but we don't distinguish, also close)
// So, we can continue receive message
if (revents_ & (POLLIN | POLLPRI | POLLRDHUP)) {
if (read_callback_) read_callback_(receive_time);
}

if (revents_ & POLLOUT) {
if (write_callback_) write_callback_();
}

// ...
}

更上层的事件处理器