]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/epollmplexer.cc
9 #include <boost/lexical_cast.hpp>
12 #include <sys/epoll.h>
15 #include "namespaces.hh"
16 #include "namespaces.hh"
18 class EpollFDMultiplexer
: public FDMultiplexer
22 virtual ~EpollFDMultiplexer()
27 virtual int run(struct timeval
* tv
);
29 virtual void addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
);
30 virtual void removeFD(callbackmap_t
& cbmap
, int fd
);
37 boost::shared_array
<epoll_event
> d_eevents
;
38 static int s_maxevents
; // not a hard maximum
42 static FDMultiplexer
* makeEpoll()
44 return new EpollFDMultiplexer();
47 static struct EpollRegisterOurselves
49 EpollRegisterOurselves() {
50 FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makeEpoll
)); // priority 0!
55 int EpollFDMultiplexer::s_maxevents
=1024;
56 EpollFDMultiplexer::EpollFDMultiplexer() : d_eevents(new epoll_event
[s_maxevents
])
58 d_epollfd
=epoll_create(s_maxevents
); // not hard max
60 throw FDMultiplexerException("Setting up epoll: "+stringerror());
61 int fd
=socket(AF_INET
, SOCK_DGRAM
, 0); // for self-test
70 catch(FDMultiplexerException
&fe
) {
73 throw FDMultiplexerException("epoll multiplexer failed self-test: "+string(fe
.what()));
78 void EpollFDMultiplexer::addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
)
80 accountingAddFD(cbmap
, fd
, toDo
, parameter
);
82 struct epoll_event eevent
;
84 eevent
.events
= (&cbmap
== &d_readCallbacks
) ? EPOLLIN
: EPOLLOUT
;
86 eevent
.data
.u64
=0; // placate valgrind (I love it so much)
89 if(epoll_ctl(d_epollfd
, EPOLL_CTL_ADD
, fd
, &eevent
) < 0) {
91 throw FDMultiplexerException("Adding fd to epoll set: "+stringerror());
95 void EpollFDMultiplexer::removeFD(callbackmap_t
& cbmap
, int fd
)
98 throw FDMultiplexerException("Tried to remove unlisted fd "+lexical_cast
<string
>(fd
)+ " from multiplexer");
100 struct epoll_event dummy
;
104 if(epoll_ctl(d_epollfd
, EPOLL_CTL_DEL
, fd
, &dummy
) < 0)
105 throw FDMultiplexerException("Removing fd from epoll set: "+stringerror());
108 int EpollFDMultiplexer::run(struct timeval
* now
)
111 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
114 int ret
=epoll_wait(d_epollfd
, d_eevents
.get(), s_maxevents
, 500);
115 gettimeofday(now
,0); // MANDATORY
117 if(ret
< 0 && errno
!=EINTR
)
118 throw FDMultiplexerException("epoll returned error: "+stringerror());
120 if(ret
< 1) // thanks AB!
124 for(int n
=0; n
< ret
; ++n
) {
125 d_iter
=d_readCallbacks
.find(d_eevents
[n
].data
.fd
);
127 if(d_iter
!= d_readCallbacks
.end()) {
128 d_iter
->second
.d_callback(d_iter
->first
, d_iter
->second
.d_parameter
);
129 continue; // so we don't refind ourselves as writable!
131 d_iter
=d_writeCallbacks
.find(d_eevents
[n
].data
.fd
);
133 if(d_iter
!= d_writeCallbacks
.end()) {
134 d_iter
->second
.d_callback(d_iter
->first
, d_iter
->second
.d_parameter
);
142 void acceptData(int fd
, funcparam_t
& parameter
)
144 cout
<<"Have data on fd "<<fd
<<endl
;
145 Socket
* sock
=funcparam_t_cast
<Socket
*>(parameter
);
148 sock
->recvFrom(packet
, rem
);
149 cout
<<"Received "<<packet
.size()<<" bytes!\n";
155 Socket
s(AF_INET
, SOCK_DGRAM
);
157 IPEndpoint
loc("0.0.0.0", 2000);
160 EpollFDMultiplexer sfm
;
162 sfm
.addReadFD(s
.getHandle(), &acceptData
, &s
);
164 for(int n
=0; n
< 100 ; ++n
) {
167 sfm
.removeReadFD(s
.getHandle());
168 sfm
.removeReadFD(s
.getHandle());