The several classes defined in Moduo: TcpServer, Acceptor, TcpConnection, EventLoop, epoller, channel, eventLoopThread, eventLoopThreadPool.
1) TcpServer construction
each TcpServer suppose have multi- tcp connections, the acceptor works as the main I/O thread, which listen the server-side I/O socket, and handle all client input connections at first, (later will assign the connection task to each worker thread from pool). so the input argument “loop” during TcpServer construction is the main I/O eventLoop.
|
|
does each worker thread run EventLoop.loop(), which will call epoll_wait(), and execute all active channels? suppose no.
3) TcpConnection construction
each new client connection will reponse to a new socket fd, and a new channel. (channel is actually the container of socket fd); and the functors on this connection is also imported to channel callbacks. basically from outside, we only see channel objects, TcpConnection object is the inner class.
|
|
so where are channel (read/write/error/close) handleEvent callbacks triggered? it is during the eventloop.loop, after epoller return the active events, based on the status of each revent, special handleEvent is called.
4) eventLoop construction
during constrution of eventLoop, a new poller is created based on this eventLoop itself, also a new wakeupfd and a new wakeupChannel. the purpose of wakeup fd/channel is to immediately wake up the work thread, rather than waiting till PollTime. and the wakeupfd bind handleRead, in which read one byte to make this wakeupfd I/O readable, which then is ready for I/O.
|
|
“activeChannels” suppose to be a class variable, which is shared by eventLoop objects, but it’s ok to keep a copy for each eventLoop object to avoid multi-thread competing. and suppose epoll_wait() is thread-safe, so later during construction of eventLoopThreadPool, multi eventLoopThreads won’t conflict with “active channels”
5) epoller construction
epoller object is created during eventloop construction. since the three interface of epoll instance are thread-safe, they look like global funcs.
epoll_create(), return an epfd referring to the new epoll instance, this epfd is used by all subsequent calsl to the epoll interface.
epoll_wait(), return all ready events on the epoll instance referred by epfd.
epoll_ctl(), traverse the red-black tree strucutre to return the existing fd, or add new fd to the tree.
6) channel construction
channel is the container of one fd, and is related to one eventLoop. channel is not responsible to create/delete fd, the real owner of each fd is TcpConnection or acceptor. Channel object works like a pipe to send fd from inner object TcpConnection to the eventLoop. the advantage here is eventLoop is independent from connections.
7) channel:update()
|
|
8) one epoll + threadpool vs per thread per epoll
the first method, one global epoll listens all new connections, and send each connection callback to a new thread to execute. method 2, to listen the server I/O socket need to bind a unique epoll, in Moduo which is the acceptor epoll. then all client connection socket will be dealt with their own worker epoll.