|
|
@ -25,6 +25,7 @@ |
|
|
#include <sys/epoll.h> |
|
|
#include <sys/epoll.h> |
|
|
|
|
|
|
|
|
#include "trbase.h" |
|
|
#include "trbase.h" |
|
|
|
|
|
#include "trdata.h" |
|
|
#include "trevent.h" |
|
|
#include "trevent.h" |
|
|
|
|
|
|
|
|
#include "tr/comm_manager.h" |
|
|
#include "tr/comm_manager.h" |
|
|
@ -44,16 +45,14 @@ commManagerEpollCtor(void * _this, va_list * params) |
|
|
{ |
|
|
{ |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommManager cmgr = _this; |
|
|
TR_CommManager cmgr = _this; |
|
|
nfds_t i; |
|
|
|
|
|
|
|
|
|
|
|
TR_PARENTCALL(TR_CommManagerEpoll, _this, TR_Class, ctor, params); |
|
|
TR_PARENTCALL(TR_CommManagerEpoll, _this, TR_Class, ctor, params); |
|
|
this->handle = epoll_create(cmgr->n_endpoints); |
|
|
|
|
|
this->events = TR_malloc(sizeof(struct epoll_event) * cmgr->n_endpoints); |
|
|
|
|
|
for (i = 0; i < cmgr->n_endpoints; i++) { |
|
|
|
|
|
this->events[i].data.ptr = NULL; |
|
|
|
|
|
this->events[i].events = EPOLLET | EPOLLONESHOT; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
this->handle = epoll_create(cmgr->n_endpoints); |
|
|
|
|
|
this->read_ready = TR_new(TR_Queue); |
|
|
|
|
|
this->write_ready = TR_new(TR_Queue); |
|
|
|
|
|
|
|
|
|
|
|
this->read_ready->free_msgs = 0; |
|
|
|
|
|
this->write_ready->free_msgs = 0; |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
@ -64,8 +63,10 @@ commManagerEpollDtor(void * _this) |
|
|
{ |
|
|
{ |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommManagerEpoll this = _this; |
|
|
|
|
|
|
|
|
|
|
|
TR_delete(this->read_ready); |
|
|
|
|
|
TR_delete(this->write_ready); |
|
|
|
|
|
|
|
|
close(this->handle); |
|
|
close(this->handle); |
|
|
TR_MEM_FREE(this->events); |
|
|
|
|
|
TR_PARENTCALL(TR_CommManagerEpoll, _this, TR_Class, dtor); |
|
|
TR_PARENTCALL(TR_CommManagerEpoll, _this, TR_Class, dtor); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -75,11 +76,12 @@ TR_commManagerEpollAddEndpoint(void * _this, TR_CommEndPoint endpoint) |
|
|
{ |
|
|
{ |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommManagerEpoll this = _this; |
|
|
int handle = endpoint->transport->handle; |
|
|
int handle = endpoint->transport->handle; |
|
|
|
|
|
struct epoll_event event; |
|
|
|
|
|
|
|
|
this->events[handle].data.ptr = endpoint; |
|
|
|
|
|
this->events[handle].events |= EPOLLIN; |
|
|
|
|
|
|
|
|
event.data.ptr = endpoint; |
|
|
|
|
|
event.events = EPOLLIN | EPOLLOUT | EPOLLET; |
|
|
|
|
|
|
|
|
epoll_ctl(this->handle, EPOLL_CTL_ADD, handle, &(this->events[handle])); |
|
|
|
|
|
|
|
|
epoll_ctl(this->handle, EPOLL_CTL_ADD, handle, &event); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static |
|
|
static |
|
|
@ -88,6 +90,11 @@ TR_commManagerEpollSelect(void * _this, TR_Event event, int timeout) |
|
|
{ |
|
|
{ |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommManagerEpoll this = _this; |
|
|
int i, nevents; |
|
|
int i, nevents; |
|
|
|
|
|
TR_Queue node; |
|
|
|
|
|
|
|
|
|
|
|
if (0 != (this->read_ready->nmsg & this->write_ready->nmsg)) { |
|
|
|
|
|
timeout = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
nevents = epoll_wait(this->handle, events, MAXEVENTS, timeout); |
|
|
nevents = epoll_wait(this->handle, events, MAXEVENTS, timeout); |
|
|
|
|
|
|
|
|
@ -95,113 +102,132 @@ TR_commManagerEpollSelect(void * _this, TR_Event event, int timeout) |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)events[i].data.ptr; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)events[i].data.ptr; |
|
|
|
|
|
|
|
|
if ((events[i].events & EPOLLIN) == EPOLLIN) { |
|
|
if ((events[i].events & EPOLLIN) == EPOLLIN) { |
|
|
TR_Event event; |
|
|
|
|
|
|
|
|
|
|
|
if (TR_INSTANCE_OF(TR_TcpSocket, endpoint->transport) |
|
|
if (TR_INSTANCE_OF(TR_TcpSocket, endpoint->transport) |
|
|
&& ((TR_TcpSocket)endpoint->transport)->listen) { |
|
|
&& ((TR_TcpSocket)endpoint->transport)->listen) { |
|
|
event = TR_eventSubjectEmit( |
|
|
|
|
|
(TR_EventSubject)endpoint, |
|
|
|
|
|
TR_CET_EVENT_ACC_READY, |
|
|
|
|
|
NULL); |
|
|
|
|
|
|
|
|
TR_eventHandlerIssueEvent((TR_EventHandler)this, |
|
|
|
|
|
TR_eventSubjectEmit( |
|
|
|
|
|
(TR_EventSubject)endpoint, |
|
|
|
|
|
TR_CET_EVENT_ACC_READY, |
|
|
|
|
|
NULL)); |
|
|
} else { |
|
|
} else { |
|
|
event = TR_eventSubjectEmit( |
|
|
|
|
|
(TR_EventSubject)endpoint, |
|
|
|
|
|
TR_CEP_EVENT_READ_READY, |
|
|
|
|
|
NULL); |
|
|
|
|
|
|
|
|
if (! ((TR_EventSubject)endpoint)->fin) { |
|
|
|
|
|
TR_queuePut(this->read_ready, endpoint); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
TR_eventHandlerIssueEvent((TR_EventHandler)this, event); |
|
|
|
|
|
this->events[i].events &= ~EPOLLIN; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ((events[i].events & EPOLLOUT) == EPOLLOUT) { |
|
|
if ((events[i].events & EPOLLOUT) == EPOLLOUT) { |
|
|
TR_Event _event = TR_eventSubjectEmit( |
|
|
|
|
|
(TR_EventSubject)endpoint, |
|
|
|
|
|
TR_CEP_EVENT_WRITE_READY, |
|
|
|
|
|
NULL); |
|
|
|
|
|
|
|
|
if (TR_cepHasPendingData(endpoint) && |
|
|
|
|
|
! ((TR_EventSubject)endpoint)->fin) { |
|
|
|
|
|
TR_queuePut(this->write_ready, endpoint); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* now issue reads and write events */ |
|
|
|
|
|
for (node=this->read_ready->first; node; node=node->next) { |
|
|
|
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)node->msg; |
|
|
|
|
|
|
|
|
|
|
|
if (! TR_socketFinRd(endpoint->transport)) { |
|
|
|
|
|
TR_eventHandlerIssueEvent( |
|
|
|
|
|
(TR_EventHandler)this, |
|
|
|
|
|
TR_eventSubjectEmit( |
|
|
|
|
|
(TR_EventSubject)endpoint, |
|
|
|
|
|
TR_CEP_EVENT_READ_READY, |
|
|
|
|
|
NULL)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
TR_eventHandlerIssueEvent((TR_EventHandler)this, _event); |
|
|
|
|
|
this->events[i].events &= ~EPOLLOUT; |
|
|
|
|
|
|
|
|
for (node=this->write_ready->first; node; node=node->next) { |
|
|
|
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)node->msg; |
|
|
|
|
|
|
|
|
|
|
|
if (! TR_socketFinWr(endpoint->transport)) { |
|
|
|
|
|
TR_eventHandlerIssueEvent( |
|
|
|
|
|
(TR_EventHandler)this, |
|
|
|
|
|
TR_eventSubjectEmit( |
|
|
|
|
|
(TR_EventSubject)endpoint, |
|
|
|
|
|
TR_CEP_EVENT_WRITE_READY, |
|
|
|
|
|
NULL)); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static |
|
|
static |
|
|
void |
|
|
void |
|
|
TR_commManagerEpollEnableWrite(void * _this, TR_Event event) |
|
|
|
|
|
|
|
|
TR_commManagerEpollRemoveWrite(void * _this, TR_Event event) |
|
|
{ |
|
|
{ |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
|
|
|
|
|
|
|
|
if (! TR_socketFinWr(endpoint->transport)) { |
|
|
|
|
|
int handle = endpoint->transport->handle; |
|
|
|
|
|
|
|
|
|
|
|
this->events[handle].data.ptr = endpoint; |
|
|
|
|
|
this->events[handle].events |= EPOLLOUT; |
|
|
|
|
|
|
|
|
|
|
|
epoll_ctl(this->handle, EPOLL_CTL_MOD, handle, &(this->events[handle])); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
TR_queueDelete(this->write_ready, endpoint); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static |
|
|
static |
|
|
void |
|
|
void |
|
|
TR_commManagerEpollDisableWrite(void * _this, TR_Event event) |
|
|
|
|
|
|
|
|
TR_commManagerEpollRemoveRead(void * _this, TR_Event event) |
|
|
{ |
|
|
{ |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
|
|
int handle = endpoint->transport->handle; |
|
|
|
|
|
|
|
|
|
|
|
this->events[handle].data.ptr = endpoint; |
|
|
|
|
|
this->events[handle].events &= ~EPOLLOUT; |
|
|
|
|
|
|
|
|
|
|
|
epoll_ctl(this->handle, EPOLL_CTL_MOD, handle, &(this->events[handle])); |
|
|
|
|
|
|
|
|
TR_queueDelete(this->read_ready, endpoint); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static |
|
|
static |
|
|
void |
|
|
void |
|
|
TR_commManagerEpollEnableRead(void * _this, TR_Event event) |
|
|
|
|
|
|
|
|
TR_commManagerEpollClose(void * _this, TR_Event event) |
|
|
{ |
|
|
{ |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
|
|
|
|
|
|
|
|
if (! TR_socketFinRd(endpoint->transport)) { |
|
|
|
|
|
int handle = endpoint->transport->handle; |
|
|
|
|
|
|
|
|
|
|
|
this->events[handle].data.ptr = endpoint; |
|
|
|
|
|
this->events[handle].events |= EPOLLIN; |
|
|
|
|
|
|
|
|
TR_queueDelete(this->read_ready, endpoint); |
|
|
|
|
|
TR_queueDelete(this->write_ready, endpoint); |
|
|
|
|
|
|
|
|
epoll_ctl(this->handle, EPOLL_CTL_MOD, handle, &(this->events[handle])); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
epoll_ctl(this->handle, EPOLL_CTL_DEL, endpoint->transport->handle, NULL); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static |
|
|
static |
|
|
void |
|
|
void |
|
|
TR_commManagerEpollDisableRead(void * _this, TR_Event event) |
|
|
|
|
|
|
|
|
TR_commManagerEpollShutRead(void * _this, TR_Event event) |
|
|
{ |
|
|
{ |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
|
|
int handle = endpoint->transport->handle; |
|
|
|
|
|
|
|
|
struct epoll_event _event; |
|
|
|
|
|
|
|
|
|
|
|
TR_queueDelete(this->read_ready, endpoint); |
|
|
|
|
|
|
|
|
this->events[handle].data.ptr = endpoint; |
|
|
|
|
|
this->events[handle].events &= ~EPOLLIN; |
|
|
|
|
|
|
|
|
_event.data.ptr = endpoint; |
|
|
|
|
|
_event.events = EPOLLOUT | EPOLLET; |
|
|
|
|
|
|
|
|
epoll_ctl(this->handle, EPOLL_CTL_MOD, handle, &(this->events[handle])); |
|
|
|
|
|
|
|
|
epoll_ctl( |
|
|
|
|
|
this->handle, |
|
|
|
|
|
EPOLL_CTL_MOD, |
|
|
|
|
|
endpoint->transport->handle, |
|
|
|
|
|
&_event); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static |
|
|
static |
|
|
void |
|
|
void |
|
|
TR_commManagerEpollClose(void * _this, TR_Event event) |
|
|
|
|
|
|
|
|
TR_commManagerEpollShutWrite(void * _this, TR_Event event) |
|
|
{ |
|
|
{ |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommManagerEpoll this = _this; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
|
|
int handle = endpoint->transport->handle; |
|
|
|
|
|
|
|
|
struct epoll_event _event; |
|
|
|
|
|
|
|
|
|
|
|
TR_queueDelete(this->write_ready, endpoint); |
|
|
|
|
|
|
|
|
this->events[handle].data.ptr = NULL; |
|
|
|
|
|
this->events[handle].events = EPOLLET | EPOLLONESHOT; |
|
|
|
|
|
|
|
|
_event.data.ptr = endpoint; |
|
|
|
|
|
_event.events = EPOLLIN | EPOLLET; |
|
|
|
|
|
|
|
|
epoll_ctl(this->handle, EPOLL_CTL_DEL, handle, NULL); |
|
|
|
|
|
|
|
|
epoll_ctl( |
|
|
|
|
|
this->handle, |
|
|
|
|
|
EPOLL_CTL_MOD, |
|
|
|
|
|
endpoint->transport->handle, |
|
|
|
|
|
&_event); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void TR_commManagerEpollNoop(void * _this, TR_Event event) {} |
|
|
|
|
|
|
|
|
static |
|
|
static |
|
|
void |
|
|
void |
|
|
TR_commManagerEpollCvInit(TR_class_ptr cls) { |
|
|
TR_commManagerEpollCvInit(TR_class_ptr cls) { |
|
|
@ -211,14 +237,14 @@ TR_commManagerEpollCvInit(TR_class_ptr cls) { |
|
|
TR_INIT_IFACE(TR_Class, commManagerEpollCtor, commManagerEpollDtor, NULL); |
|
|
TR_INIT_IFACE(TR_Class, commManagerEpollCtor, commManagerEpollDtor, NULL); |
|
|
TR_INIT_IFACE( |
|
|
TR_INIT_IFACE( |
|
|
TR_CommManager, |
|
|
TR_CommManager, |
|
|
TR_commManagerEpollAddEndpoint, |
|
|
|
|
|
TR_commManagerEpollSelect, |
|
|
|
|
|
TR_commManagerEpollEnableWrite, |
|
|
|
|
|
TR_commManagerEpollDisableWrite, |
|
|
|
|
|
TR_commManagerEpollEnableRead, |
|
|
|
|
|
TR_commManagerEpollClose, |
|
|
|
|
|
TR_commManagerEpollDisableRead, |
|
|
|
|
|
TR_commManagerEpollDisableWrite); |
|
|
|
|
|
|
|
|
TR_commManagerEpollAddEndpoint, // TR_CON_EVENT_NEW_CON |
|
|
|
|
|
TR_commManagerEpollSelect, // TR_DISPATCHER_EVENT_DATA_WAIT |
|
|
|
|
|
TR_commManagerEpollRemoveWrite, // TR_CEP_EVENT_PENDING_DATA => WRITE_BLOCK |
|
|
|
|
|
TR_commManagerEpollNoop, // TR_CEP_EVENT_END_DATA |
|
|
|
|
|
TR_commManagerEpollRemoveRead, // TR_CEP_EVENT_READ_BLOCK |
|
|
|
|
|
TR_commManagerEpollClose, // TR_CEP_EVENT_CLOSE |
|
|
|
|
|
TR_commManagerEpollShutWrite, // TR_CEP_EVENT_SHUT_READ |
|
|
|
|
|
TR_commManagerEpollShutRead); // TR_CEP_EVENT_SHUT_WRITE |
|
|
TR_CREATE_CLASS( |
|
|
TR_CREATE_CLASS( |
|
|
TR_CommManagerEpoll, |
|
|
TR_CommManagerEpoll, |
|
|
TR_CommManager, |
|
|
TR_CommManager, |
|
|
|