]>
Commit | Line | Data |
---|---|---|
ab3e8a6c BH |
1 | #include <boost/function.hpp> |
2 | #include <boost/any.hpp> | |
a1dfcec8 | 3 | #include <boost/shared_array.hpp> |
0bff046b BH |
4 | #include <boost/tuple/tuple.hpp> |
5 | #include <boost/tuple/tuple_comparison.hpp> | |
6 | #include <vector> | |
ab3e8a6c BH |
7 | #include <map> |
8 | #include <stdexcept> | |
9 | #include <string> | |
10 | ||
11 | class FDMultiplexerException : public std::runtime_error | |
12 | { | |
13 | public: | |
14 | FDMultiplexerException(const std::string& str) : std::runtime_error(str) | |
15 | {} | |
16 | }; | |
17 | ||
a1dfcec8 BH |
18 | |
19 | /** Very simple FD multiplexer, based on callbacks and boost::any parameters | |
20 | As a special service, this parameter is kept around and can be modified, | |
21 | allowing for state to be stored inside the multiplexer. | |
22 | ||
23 | It has some "interesting" semantics | |
24 | */ | |
1f4abb20 | 25 | |
ab3e8a6c BH |
26 | class FDMultiplexer |
27 | { | |
28 | protected: | |
29 | typedef boost::function< void(int, boost::any&) > callbackfunc_t; | |
30 | struct Callback | |
31 | { | |
32 | callbackfunc_t d_callback; | |
33 | boost::any d_parameter; | |
0bff046b | 34 | struct timeval d_ttd; |
ab3e8a6c BH |
35 | }; |
36 | ||
37 | public: | |
38 | FDMultiplexer() : d_inrun(false) | |
39 | {} | |
40 | virtual ~FDMultiplexer() | |
41 | {} | |
42 | ||
0bff046b | 43 | virtual int run(struct timeval* tv) = 0; |
ab3e8a6c | 44 | |
a1dfcec8 | 45 | //! Add an fd to the read watch list - currently an fd can only be on one list at a time! |
ab3e8a6c BH |
46 | virtual void addReadFD(int fd, callbackfunc_t toDo, boost::any parameter=boost::any()) |
47 | { | |
a1dfcec8 | 48 | this->addFD(d_readCallbacks, fd, toDo, parameter); |
ab3e8a6c BH |
49 | } |
50 | ||
a1dfcec8 | 51 | //! Add an fd to the write watch list - currently an fd can only be on one list at a time! |
ab3e8a6c BH |
52 | virtual void addWriteFD(int fd, callbackfunc_t toDo, boost::any parameter=boost::any()) |
53 | { | |
a1dfcec8 | 54 | this->addFD(d_writeCallbacks, fd, toDo, parameter); |
ab3e8a6c BH |
55 | } |
56 | ||
a1dfcec8 | 57 | //! Remove an fd from the read watch list. You can't call this function on an fd that is closed already! |
6dcd28c3 | 58 | /** WARNING: references to 'parameter' become invalid after this function! */ |
ab3e8a6c BH |
59 | virtual void removeReadFD(int fd) |
60 | { | |
a1dfcec8 | 61 | this->removeFD(d_readCallbacks, fd); |
ab3e8a6c BH |
62 | } |
63 | ||
a1dfcec8 | 64 | //! Remove an fd from the write watch list. You can't call this function on an fd that is closed already! |
6dcd28c3 | 65 | /** WARNING: references to 'parameter' become invalid after this function! */ |
a1dfcec8 | 66 | virtual void removeWriteFD(int fd) |
ab3e8a6c | 67 | { |
a1dfcec8 | 68 | this->removeFD(d_writeCallbacks, fd); |
ab3e8a6c BH |
69 | } |
70 | ||
0bff046b BH |
71 | virtual void setReadTTD(int fd, struct timeval tv, int timeout) |
72 | { | |
73 | if(!d_readCallbacks.count(fd)) | |
74 | throw FDMultiplexerException("attempt to timestamp fd not in the multiplexer"); | |
75 | tv.tv_sec += timeout; | |
76 | d_readCallbacks[fd].d_ttd=tv; | |
77 | } | |
78 | ||
79 | virtual std::vector<std::pair<int, boost::any> > getTimeouts(const struct timeval& tv) | |
80 | { | |
81 | std::vector<std::pair<int, boost::any> > ret; | |
82 | for(callbackmap_t::iterator i=d_readCallbacks.begin(); i!=d_readCallbacks.end(); ++i) | |
83 | if(i->second.d_ttd.tv_sec && boost::tie(tv.tv_sec, tv.tv_usec) > boost::tie(i->second.d_ttd.tv_sec, i->second.d_ttd.tv_usec)) | |
84 | ret.push_back(std::make_pair(i->first, i->second.d_parameter)); | |
85 | return ret; | |
86 | } | |
87 | ||
1f4abb20 BH |
88 | typedef FDMultiplexer* getMultiplexer_t(); |
89 | typedef std::multimap<int, getMultiplexer_t*> FDMultiplexermap_t; | |
90 | ||
91 | static FDMultiplexermap_t& getMultiplexerMap() | |
92 | { | |
93 | static FDMultiplexermap_t theMap; | |
94 | return theMap; | |
95 | } | |
96 | ||
97 | virtual std::string getName() = 0; | |
98 | ||
ab3e8a6c BH |
99 | protected: |
100 | typedef std::map<int, Callback> callbackmap_t; | |
101 | callbackmap_t d_readCallbacks, d_writeCallbacks; | |
ab3e8a6c BH |
102 | |
103 | virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, boost::any parameter)=0; | |
104 | virtual void removeFD(callbackmap_t& cbmap, int fd)=0; | |
105 | bool d_inrun; | |
a1dfcec8 | 106 | callbackmap_t::iterator d_iter; |
1f4abb20 BH |
107 | }; |
108 | ||
109 | class SelectFDMultiplexer : public FDMultiplexer | |
110 | { | |
111 | public: | |
112 | SelectFDMultiplexer() | |
113 | {} | |
114 | virtual ~SelectFDMultiplexer() | |
115 | {} | |
ab3e8a6c | 116 | |
0bff046b | 117 | virtual int run(struct timeval* tv); |
1f4abb20 BH |
118 | |
119 | virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, boost::any parameter); | |
120 | virtual void removeFD(callbackmap_t& cbmap, int fd); | |
121 | std::string getName() | |
122 | { | |
123 | return "select"; | |
124 | } | |
ab3e8a6c BH |
125 | }; |
126 |