]>
Commit | Line | Data |
---|---|---|
870a0fe4 AT |
1 | #ifdef HAVE_CONFIG_H |
2 | #include "config.h" | |
3 | #endif | |
ab3e8a6c BH |
4 | #include "mplexer.hh" |
5 | #include "sstuff.hh" | |
6 | #include <iostream> | |
ab3e8a6c | 7 | #include "misc.hh" |
ab3e8a6c | 8 | |
10f4eea8 | 9 | #include "namespaces.hh" |
ab3e8a6c | 10 | |
1f4abb20 | 11 | static FDMultiplexer* make() |
a1dfcec8 BH |
12 | { |
13 | return new SelectFDMultiplexer(); | |
14 | } | |
15 | ||
1f4abb20 BH |
16 | static struct RegisterOurselves |
17 | { | |
18 | RegisterOurselves() { | |
19 | FDMultiplexer::getMultiplexerMap().insert(make_pair(1, &make)); | |
20 | } | |
21 | } doIt; | |
a1dfcec8 | 22 | |
c454d11b | 23 | void SelectFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter) |
ab3e8a6c BH |
24 | { |
25 | Callback cb; | |
26 | cb.d_callback=toDo; | |
27 | cb.d_parameter=parameter; | |
0bff046b | 28 | memset(&cb.d_ttd, 0, sizeof(cb.d_ttd)); |
ab3e8a6c | 29 | if(cbmap.count(fd)) |
335da0ba | 30 | throw FDMultiplexerException("Tried to add fd "+std::to_string(fd)+ " to multiplexer twice"); |
ab3e8a6c BH |
31 | cbmap[fd]=cb; |
32 | } | |
33 | ||
34 | void SelectFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd) | |
35 | { | |
a1dfcec8 BH |
36 | if(d_inrun && d_iter->first==fd) // trying to remove us! |
37 | d_iter++; | |
38 | ||
ab3e8a6c | 39 | if(!cbmap.erase(fd)) |
335da0ba | 40 | throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer"); |
ab3e8a6c BH |
41 | } |
42 | ||
0e663c3b | 43 | int SelectFDMultiplexer::run(struct timeval* now, int timeout) |
ab3e8a6c | 44 | { |
a1dfcec8 BH |
45 | if(d_inrun) { |
46 | throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n"); | |
47 | } | |
ab3e8a6c BH |
48 | fd_set readfds, writefds; |
49 | FD_ZERO(&readfds); | |
50 | FD_ZERO(&writefds); | |
51 | ||
52 | int fdmax=0; | |
53 | ||
54 | for(callbackmap_t::const_iterator i=d_readCallbacks.begin(); i != d_readCallbacks.end(); ++i) { | |
55 | FD_SET(i->first, &readfds); | |
56 | fdmax=max(i->first, fdmax); | |
57 | } | |
a1dfcec8 BH |
58 | |
59 | for(callbackmap_t::const_iterator i=d_writeCallbacks.begin(); i != d_writeCallbacks.end(); ++i) { | |
60 | FD_SET(i->first, &writefds); | |
61 | fdmax=max(i->first, fdmax); | |
62 | } | |
ab3e8a6c | 63 | |
0e663c3b | 64 | struct timeval tv={timeout / 1000 , (timeout % 1000) * 1000}; |
ab3e8a6c | 65 | int ret=select(fdmax + 1, &readfds, &writefds, 0, &tv); |
0e663c3b | 66 | gettimeofday(now, 0); // MANDATORY! |
ab3e8a6c BH |
67 | |
68 | if(ret < 0 && errno!=EINTR) | |
69 | throw FDMultiplexerException("select returned error: "+stringerror()); | |
70 | ||
f3c5773b | 71 | if(ret < 1) // nothing - thanks AB |
ab3e8a6c BH |
72 | return 0; |
73 | ||
a1dfcec8 | 74 | d_iter=d_readCallbacks.end(); |
ab3e8a6c | 75 | d_inrun=true; |
0e663c3b RG |
76 | |
77 | int got = 0; | |
a1dfcec8 BH |
78 | for(callbackmap_t::iterator i=d_readCallbacks.begin(); i != d_readCallbacks.end() && i->first <= fdmax; ) { |
79 | d_iter=i++; | |
ab3e8a6c | 80 | |
a1dfcec8 BH |
81 | if(FD_ISSET(d_iter->first, &readfds)) { |
82 | d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter); | |
0e663c3b | 83 | got++; |
abbd6830 | 84 | continue; // so we don't refind ourselves as writable |
a1dfcec8 | 85 | } |
ab3e8a6c BH |
86 | } |
87 | ||
a1dfcec8 BH |
88 | for(callbackmap_t::iterator i=d_writeCallbacks.begin(); i != d_writeCallbacks.end() && i->first <= fdmax; ) { |
89 | d_iter=i++; | |
90 | if(FD_ISSET(d_iter->first, &writefds)) { | |
91 | d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter); | |
0e663c3b | 92 | got++; |
a1dfcec8 BH |
93 | } |
94 | } | |
ab3e8a6c BH |
95 | |
96 | d_inrun=false; | |
0e663c3b | 97 | return got; |
ab3e8a6c BH |
98 | } |
99 | ||
a1dfcec8 BH |
100 | #if 0 |
101 | ||
ab3e8a6c BH |
102 | void acceptData(int fd, boost::any& parameter) |
103 | { | |
104 | cout<<"Have data on fd "<<fd<<endl; | |
105 | Socket* sock=boost::any_cast<Socket*>(parameter); | |
106 | string packet; | |
107 | IPEndpoint rem; | |
108 | sock->recvFrom(packet, rem); | |
109 | cout<<"Received "<<packet.size()<<" bytes!\n"; | |
110 | } | |
111 | ||
a1dfcec8 | 112 | |
ab3e8a6c BH |
113 | int main() |
114 | { | |
a5794017 | 115 | Socket s(AF_INET, SOCK_DGRAM); |
ab3e8a6c BH |
116 | |
117 | IPEndpoint loc("0.0.0.0", 2000); | |
118 | s.bind(loc); | |
119 | ||
120 | SelectFDMultiplexer sfm; | |
121 | ||
122 | sfm.addReadFD(s.getHandle(), &acceptData, &s); | |
123 | ||
124 | for(int n=0; n < 100 ; ++n) { | |
125 | sfm.run(); | |
126 | } | |
127 | sfm.removeReadFD(s.getHandle()); | |
128 | sfm.removeReadFD(s.getHandle()); | |
129 | } | |
130 | #endif | |
131 |