]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/devpollmplexer.cc
fix up makecontext for Solaris, thanks to John Levon for pointing out how. Solaris...
[thirdparty/pdns.git] / pdns / devpollmplexer.cc
CommitLineData
781d550a
BH
1#include <sys/devpoll.h>
2#include "mplexer.hh"
3#include "sstuff.hh"
4#include <iostream>
5#include <unistd.h>
6#include "misc.hh"
7#include <boost/lexical_cast.hpp>
8#include "syncres.hh"
9
61b26744 10#include "namespaces.hh"
781d550a
BH
11using namespace std;
12
13class DevPollFDMultiplexer : public FDMultiplexer
14{
15public:
16 DevPollFDMultiplexer();
17 virtual ~DevPollFDMultiplexer()
18 {
19 close(d_devpollfd);
20 }
21
22 virtual int run(struct timeval* tv);
23
24 virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter);
25 virtual void removeFD(callbackmap_t& cbmap, int fd);
26 string getName()
27 {
28 return "/dev/poll";
29 }
30private:
31 int d_devpollfd;
32};
33
34
35static FDMultiplexer* makeDevPoll()
36{
37 return new DevPollFDMultiplexer();
38}
39
40static struct DevPollRegisterOurselves
41{
42 DevPollRegisterOurselves() {
43 FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makeDevPoll)); // priority 0!
44 }
45} doItDevPoll;
46
47
48//int DevPollFDMultiplexer::s_maxevents=1024;
49DevPollFDMultiplexer::DevPollFDMultiplexer()
50{
51 d_devpollfd=open("/dev/poll", O_RDWR);
52 if(d_devpollfd < 0)
53 throw FDMultiplexerException("Setting up /dev/poll: "+stringerror());
54
55}
56
57void DevPollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter)
58{
59 accountingAddFD(cbmap, fd, toDo, parameter);
60
61 struct pollfd devent;
62 devent.fd=fd;
63 devent.events= (&cbmap == &d_readCallbacks) ? POLLIN : POLLOUT;
64 devent.revents = 0;
65
66 if(write(d_devpollfd, &devent, sizeof(devent)) != sizeof(devent)) {
67 cbmap.erase(fd);
68 throw FDMultiplexerException("Adding fd to /dev/poll/ set: "+stringerror());
69 }
70}
71
72void DevPollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
73{
74 if(!cbmap.erase(fd))
75 throw FDMultiplexerException("Tried to remove unlisted fd "+lexical_cast<string>(fd)+ " from multiplexer");
76
77 struct pollfd devent;
78 devent.fd=fd;
79 devent.events= POLLREMOVE;
80 devent.revents = 0;
81
82 if(write(d_devpollfd, &devent, sizeof(devent)) != sizeof(devent)) {
83 cbmap.erase(fd);
84 throw FDMultiplexerException("Removing fd from epoll set: "+stringerror());
85 }
86}
87
88int DevPollFDMultiplexer::run(struct timeval* now)
89{
90 if(d_inrun) {
91 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
92 }
93 struct dvpoll dvp;
94 dvp.dp_nfds = d_readCallbacks.size() + d_writeCallbacks.size();
95 dvp.dp_fds = new pollfd[dvp.dp_nfds];
96 dvp.dp_timeout = 500;
97 int ret=ioctl(d_devpollfd, DP_POLL, &dvp);
98 gettimeofday(now,0);
99
100 if(ret < 0 && errno!=EINTR)
101 throw FDMultiplexerException("/dev/poll returned error: "+stringerror());
102
103 if(ret < 1) // thanks AB!
104 return 0;
105
106 d_inrun=true;
107 for(int n=0; n < ret; ++n) {
108 d_iter=d_readCallbacks.find(dvp.dp_fds[n].fd);
109
110 if(d_iter != d_readCallbacks.end()) {
111 d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter);
112 continue; // so we don't refind ourselves as writable!
113 }
114 d_iter=d_writeCallbacks.find(dvp.dp_fds[n].fd);
115
116 if(d_iter != d_writeCallbacks.end()) {
117 d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter);
118 }
119 }
120 delete[] dvp.dp_fds;
121 d_inrun=false;
122 return 0;
123}
124
125#if 0
126void acceptData(int fd, funcparam_t& parameter)
127{
128 cout<<"Have data on fd "<<fd<<endl;
129 Socket* sock=funcparam_t_cast<Socket*>(parameter);
130 string packet;
131 IPEndpoint rem;
132 sock->recvFrom(packet, rem);
133 cout<<"Received "<<packet.size()<<" bytes!\n";
134}
135
136
137int main()
138{
139 Socket s(InterNetwork, Datagram);
140
141 IPEndpoint loc("0.0.0.0", 2000);
142 s.bind(loc);
143
144 DevPollFDMultiplexer sfm;
145
146 sfm.addReadFD(s.getHandle(), &acceptData, &s);
147
148 for(int n=0; n < 100 ; ++n) {
149 sfm.run();
150 }
151 sfm.removeReadFD(s.getHandle());
152 sfm.removeReadFD(s.getHandle());
153}
154#endif
155
156