6 changed files with 252 additions and 1 deletions
-
1include/Makefile.am
-
44include/tr/comm_manager_epoll.h
-
1include/trcomm.h
-
1src/Makefile.am
-
203src/comm_manager_epoll.c
-
3src/server.c
@ -0,0 +1,44 @@ |
|||||
|
/** |
||||
|
* \file |
||||
|
* |
||||
|
* \author Georg Hopp |
||||
|
* |
||||
|
* \copyright |
||||
|
* Copyright © 2014 Georg Hopp |
||||
|
* |
||||
|
* This program is free software: you can redistribute it and/or modify |
||||
|
* it under the terms of the GNU General Public License as published by |
||||
|
* the Free Software Foundation, either version 3 of the License, or |
||||
|
* (at your option) any later version. |
||||
|
* |
||||
|
* This program is distributed in the hope that it will be useful, |
||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
* GNU General Public License for more details. |
||||
|
* |
||||
|
* You should have received a copy of the GNU General Public License |
||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
|
*/ |
||||
|
|
||||
|
#ifndef __TR_COMM_MANAGER_EPOLL_H__ |
||||
|
#define __TR_COMM_MANAGER_EPOLL_H__ |
||||
|
|
||||
|
#include <sys/types.h> |
||||
|
|
||||
|
#include "trbase.h" |
||||
|
#include "trevent.h" |
||||
|
|
||||
|
TR_CLASS(TR_CommManagerEpoll) { |
||||
|
TR_EXTENDS(TR_CommManager); |
||||
|
|
||||
|
int handle; |
||||
|
}; |
||||
|
TR_INSTANCE_INIT(TR_CommManagerEpoll); |
||||
|
TR_CLASSVARS_DECL(TR_CommManagerEpoll) { |
||||
|
TR_CV_EXTENDS(TR_EventHandler); |
||||
|
}; |
||||
|
|
||||
|
#endif // __TR_COMM_MANAGER_EPOLL_H__ |
||||
|
|
||||
|
// vim: set ts=4 sw=4: |
||||
|
|
||||
@ -0,0 +1,203 @@ |
|||||
|
/** |
||||
|
* \file |
||||
|
* |
||||
|
* \author Georg Hopp |
||||
|
* |
||||
|
* \copyright |
||||
|
* Copyright © 2014 Georg Hopp |
||||
|
* |
||||
|
* This program is free software: you can redistribute it and/or modify |
||||
|
* it under the terms of the GNU General Public License as published by |
||||
|
* the Free Software Foundation, either version 3 of the License, or |
||||
|
* (at your option) any later version. |
||||
|
* |
||||
|
* This program is distributed in the hope that it will be useful, |
||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
* GNU General Public License for more details. |
||||
|
* |
||||
|
* You should have received a copy of the GNU General Public License |
||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
|
*/ |
||||
|
|
||||
|
#include <unistd.h> |
||||
|
#include <poll.h> |
||||
|
#include <sys/epoll.h> |
||||
|
|
||||
|
#include "trbase.h" |
||||
|
#include "trevent.h" |
||||
|
|
||||
|
#include "tr/comm_manager.h" |
||||
|
#include "tr/comm_manager_epoll.h" |
||||
|
#include "tr/interface/comm_manager.h" |
||||
|
#include "tr/comm_end_point.h" |
||||
|
#include "tr/connection.h" |
||||
|
#include "tr/connect_entry_point.h" |
||||
|
|
||||
|
#define MAXEVENTS 64 |
||||
|
|
||||
|
struct epoll_event events[64]; |
||||
|
|
||||
|
static |
||||
|
int |
||||
|
commManagerEpollCtor(void * _this, va_list * params) |
||||
|
{ |
||||
|
TR_CommManagerEpoll this = _this; |
||||
|
TR_CommManager cmgr = _this; |
||||
|
|
||||
|
TR_PARENTCALL(TR_CommManagerEpoll, _this, TR_Class, ctor, params); |
||||
|
this->handle = epoll_create(cmgr->n_endpoints); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
commManagerEpollDtor(void * _this) |
||||
|
{ |
||||
|
TR_CommManagerEpoll this = _this; |
||||
|
|
||||
|
close(this->handle); |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
TR_commManagerEpollAddEndpoint(void * _this, TR_CommEndPoint endpoint) |
||||
|
{ |
||||
|
TR_CommManagerEpoll this = _this; |
||||
|
struct epoll_event event; |
||||
|
|
||||
|
event.data.ptr = endpoint; |
||||
|
event.events = EPOLLIN | EPOLLET; |
||||
|
|
||||
|
epoll_ctl(this->handle, EPOLL_CTL_ADD, endpoint->transport->handle, &event); |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
TR_commManagerEpollSelect(void * _this, TR_Event event, int timeout) |
||||
|
{ |
||||
|
TR_CommManagerEpoll this = _this; |
||||
|
int i, nevents; |
||||
|
|
||||
|
nevents = epoll_wait(this->handle, events, MAXEVENTS, timeout); |
||||
|
|
||||
|
for (i=0; i<nevents; i++) { |
||||
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)events[i].data.ptr; |
||||
|
|
||||
|
if ((events[i].events & POLLIN) == POLLIN) { |
||||
|
TR_Event event; |
||||
|
|
||||
|
if (TR_INSTANCE_OF(TR_TcpSocket, endpoint->transport) |
||||
|
&& ((TR_TcpSocket)endpoint->transport)->listen) { |
||||
|
event = TR_eventSubjectEmit( |
||||
|
(TR_EventSubject)endpoint, |
||||
|
TR_CET_EVENT_ACC_READY, |
||||
|
NULL); |
||||
|
} else { |
||||
|
event = TR_eventSubjectEmit( |
||||
|
(TR_EventSubject)endpoint, |
||||
|
TR_CEP_EVENT_READ_READY, |
||||
|
NULL); |
||||
|
} |
||||
|
|
||||
|
TR_eventHandlerIssueEvent((TR_EventHandler)this, event); |
||||
|
} |
||||
|
|
||||
|
if ((events[i].events & POLLOUT) == POLLOUT) { |
||||
|
TR_eventHandlerIssueEvent( |
||||
|
(TR_EventHandler)this, |
||||
|
TR_eventSubjectEmit( |
||||
|
(TR_EventSubject)endpoint, |
||||
|
TR_CEP_EVENT_WRITE_READY, |
||||
|
NULL)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
TR_commManagerEpollEnableWrite(void * _this, TR_Event event) |
||||
|
{ |
||||
|
TR_CommManagerEpoll this = _this; |
||||
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
||||
|
|
||||
|
if (! TR_socketFinWr(endpoint->transport)) { |
||||
|
struct epoll_event epevent; |
||||
|
|
||||
|
epevent.data.ptr = endpoint; |
||||
|
epevent.events = EPOLLOUT | EPOLLIN | EPOLLET; |
||||
|
|
||||
|
epoll_ctl( |
||||
|
this->handle, |
||||
|
EPOLL_CTL_MOD, |
||||
|
endpoint->transport->handle, |
||||
|
&epevent); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
TR_commManagerEpollDisableWrite(void * _this, TR_Event event) |
||||
|
{ |
||||
|
TR_CommManagerEpoll this = _this; |
||||
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
||||
|
struct epoll_event epevent; |
||||
|
|
||||
|
epevent.data.ptr = endpoint; |
||||
|
epevent.events = EPOLLIN | EPOLLET; |
||||
|
|
||||
|
epoll_ctl( |
||||
|
this->handle, |
||||
|
EPOLL_CTL_MOD, |
||||
|
endpoint->transport->handle, |
||||
|
&epevent); |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
TR_commManagerEpollClose(void * _this, TR_Event event) |
||||
|
{ |
||||
|
TR_CommManagerEpoll this = _this; |
||||
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject; |
||||
|
|
||||
|
epoll_ctl(this->handle, EPOLL_CTL_DEL, endpoint->transport->handle, NULL); |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
TR_commManagerEpollEnableRead(void * _this, TR_Event event) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
TR_commManagerEpollDisableRead(void * _this, TR_Event event) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
TR_commManagerEpollCvInit(TR_class_ptr cls) { |
||||
|
TR_INHERIT_CLASSVARS(TR_CommManagerEpoll, TR_CommManager); |
||||
|
} |
||||
|
|
||||
|
TR_INIT_IFACE(TR_Class, commManagerEpollCtor, commManagerEpollDtor, NULL); |
||||
|
TR_INIT_IFACE( |
||||
|
TR_CommManager, |
||||
|
TR_commManagerEpollAddEndpoint, |
||||
|
TR_commManagerEpollSelect, |
||||
|
TR_commManagerEpollEnableWrite, |
||||
|
TR_commManagerEpollDisableWrite, |
||||
|
TR_commManagerEpollEnableRead, |
||||
|
TR_commManagerEpollClose, |
||||
|
TR_commManagerEpollDisableRead, |
||||
|
TR_commManagerEpollDisableWrite); |
||||
|
TR_CREATE_CLASS( |
||||
|
TR_CommManagerEpoll, |
||||
|
TR_CommManager, |
||||
|
TR_commManagerEpollCvInit, |
||||
|
TR_IF(TR_Class), |
||||
|
TR_IF(TR_CommManager)); |
||||
|
|
||||
|
// vim: set ts=4 sw=4: |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue