]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/epollmplexer.cc
11 #include <sys/epoll.h>
14 #include "namespaces.hh"
15 #include "namespaces.hh"
17 class EpollFDMultiplexer
: public FDMultiplexer
21 virtual ~EpollFDMultiplexer()
26 virtual int run(struct timeval
* tv
);
28 virtual void addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
);
29 virtual void removeFD(callbackmap_t
& cbmap
, int fd
);
36 boost::shared_array
<epoll_event
> d_eevents
;
37 static int s_maxevents
; // not a hard maximum
41 static FDMultiplexer
* makeEpoll()
43 return new EpollFDMultiplexer();
46 static struct EpollRegisterOurselves
48 EpollRegisterOurselves() {
49 FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makeEpoll
)); // priority 0!
54 int EpollFDMultiplexer::s_maxevents
=1024;
55 EpollFDMultiplexer::EpollFDMultiplexer() : d_eevents(new epoll_event
[s_maxevents
])
57 d_epollfd
=epoll_create(s_maxevents
); // not hard max
59 throw FDMultiplexerException("Setting up epoll: "+stringerror());
60 int fd
=socket(AF_INET
, SOCK_DGRAM
, 0); // for self-test
69 catch(FDMultiplexerException
&fe
) {
72 throw FDMultiplexerException("epoll multiplexer failed self-test: "+string(fe
.what()));
77 void EpollFDMultiplexer::addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
)
79 accountingAddFD(cbmap
, fd
, toDo
, parameter
);
81 struct epoll_event eevent
;
83 eevent
.events
= (&cbmap
== &d_readCallbacks
) ? EPOLLIN
: EPOLLOUT
;
85 eevent
.data
.u64
=0; // placate valgrind (I love it so much)
88 if(epoll_ctl(d_epollfd
, EPOLL_CTL_ADD
, fd
, &eevent
) < 0) {
90 throw FDMultiplexerException("Adding fd to epoll set: "+stringerror());
94 void EpollFDMultiplexer::removeFD(callbackmap_t
& cbmap
, int fd
)
97 throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd
)+ " from multiplexer");
99 struct epoll_event dummy
;
103 if(epoll_ctl(d_epollfd
, EPOLL_CTL_DEL
, fd
, &dummy
) < 0)
104 throw FDMultiplexerException("Removing fd from epoll set: "+stringerror());
107 int EpollFDMultiplexer::run(struct timeval
* now
)
110 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
113 int ret
=epoll_wait(d_epollfd
, d_eevents
.get(), s_maxevents
, 500);
114 gettimeofday(now
,0); // MANDATORY
116 if(ret
< 0 && errno
!=EINTR
)
117 throw FDMultiplexerException("epoll returned error: "+stringerror());
119 if(ret
< 1) // thanks AB!
123 for(int n
=0; n
< ret
; ++n
) {
124 d_iter
=d_readCallbacks
.find(d_eevents
[n
].data
.fd
);
126 if(d_iter
!= d_readCallbacks
.end()) {
127 d_iter
->second
.d_callback(d_iter
->first
, d_iter
->second
.d_parameter
);
128 continue; // so we don't refind ourselves as writable!
130 d_iter
=d_writeCallbacks
.find(d_eevents
[n
].data
.fd
);
132 if(d_iter
!= d_writeCallbacks
.end()) {
133 d_iter
->second
.d_callback(d_iter
->first
, d_iter
->second
.d_parameter
);
141 void acceptData(int fd
, funcparam_t
& parameter
)
143 cout
<<"Have data on fd "<<fd
<<endl
;
144 Socket
* sock
=funcparam_t_cast
<Socket
*>(parameter
);
147 sock
->recvFrom(packet
, rem
);
148 cout
<<"Received "<<packet
.size()<<" bytes!\n";
154 Socket
s(AF_INET
, SOCK_DGRAM
);
156 IPEndpoint
loc("0.0.0.0", 2000);
159 EpollFDMultiplexer sfm
;
161 sfm
.addReadFD(s
.getHandle(), &acceptData
, &s
);
163 for(int n
=0; n
< 100 ; ++n
) {
166 sfm
.removeReadFD(s
.getHandle());
167 sfm
.removeReadFD(s
.getHandle());