]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/epollmplexer.cc
6 #include <boost/lexical_cast.hpp>
12 #include "namespaces.hh"
13 #include "namespaces.hh"
15 class EpollFDMultiplexer
: public FDMultiplexer
19 virtual ~EpollFDMultiplexer()
24 virtual int run(struct timeval
* tv
);
26 virtual void addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
);
27 virtual void removeFD(callbackmap_t
& cbmap
, int fd
);
34 boost::shared_array
<epoll_event
> d_eevents
;
35 static int s_maxevents
; // not a hard maximum
39 static FDMultiplexer
* makeEpoll()
41 return new EpollFDMultiplexer();
44 static struct EpollRegisterOurselves
46 EpollRegisterOurselves() {
47 FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makeEpoll
)); // priority 0!
52 int EpollFDMultiplexer::s_maxevents
=1024;
53 EpollFDMultiplexer::EpollFDMultiplexer() : d_eevents(new epoll_event
[s_maxevents
])
55 d_epollfd
=epoll_create(s_maxevents
); // not hard max
57 throw FDMultiplexerException("Setting up epoll: "+stringerror());
58 int fd
=socket(AF_INET
, SOCK_DGRAM
, 0); // for self-test
67 catch(FDMultiplexerException
&fe
) {
70 throw FDMultiplexerException("epoll multiplexer failed self-test: "+string(fe
.what()));
75 void EpollFDMultiplexer::addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
)
77 accountingAddFD(cbmap
, fd
, toDo
, parameter
);
79 struct epoll_event eevent
;
81 eevent
.events
= (&cbmap
== &d_readCallbacks
) ? EPOLLIN
: EPOLLOUT
;
83 eevent
.data
.u64
=0; // placate valgrind (I love it so much)
86 if(epoll_ctl(d_epollfd
, EPOLL_CTL_ADD
, fd
, &eevent
) < 0) {
88 throw FDMultiplexerException("Adding fd to epoll set: "+stringerror());
92 void EpollFDMultiplexer::removeFD(callbackmap_t
& cbmap
, int fd
)
95 throw FDMultiplexerException("Tried to remove unlisted fd "+lexical_cast
<string
>(fd
)+ " from multiplexer");
97 struct epoll_event dummy
;
101 if(epoll_ctl(d_epollfd
, EPOLL_CTL_DEL
, fd
, &dummy
) < 0)
102 throw FDMultiplexerException("Removing fd from epoll set: "+stringerror());
105 int EpollFDMultiplexer::run(struct timeval
* now
)
108 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
111 int ret
=epoll_wait(d_epollfd
, d_eevents
.get(), s_maxevents
, 500);
112 gettimeofday(now
,0); // MANDATORY
114 if(ret
< 0 && errno
!=EINTR
)
115 throw FDMultiplexerException("epoll returned error: "+stringerror());
117 if(ret
< 1) // thanks AB!
121 for(int n
=0; n
< ret
; ++n
) {
122 d_iter
=d_readCallbacks
.find(d_eevents
[n
].data
.fd
);
124 if(d_iter
!= d_readCallbacks
.end()) {
125 d_iter
->second
.d_callback(d_iter
->first
, d_iter
->second
.d_parameter
);
126 continue; // so we don't refind ourselves as writable!
128 d_iter
=d_writeCallbacks
.find(d_eevents
[n
].data
.fd
);
130 if(d_iter
!= d_writeCallbacks
.end()) {
131 d_iter
->second
.d_callback(d_iter
->first
, d_iter
->second
.d_parameter
);
139 void acceptData(int fd
, funcparam_t
& parameter
)
141 cout
<<"Have data on fd "<<fd
<<endl
;
142 Socket
* sock
=funcparam_t_cast
<Socket
*>(parameter
);
145 sock
->recvFrom(packet
, rem
);
146 cout
<<"Received "<<packet
.size()<<" bytes!\n";
152 Socket
s(AF_INET
, SOCK_DGRAM
);
154 IPEndpoint
loc("0.0.0.0", 2000);
157 EpollFDMultiplexer sfm
;
159 sfm
.addReadFD(s
.getHandle(), &acceptData
, &s
);
161 for(int n
=0; n
< 100 ; ++n
) {
164 sfm
.removeReadFD(s
.getHandle());
165 sfm
.removeReadFD(s
.getHandle());