]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/mplexer.hh
teach Recursor about 'ARCHFLAGS' for -m64 and make sure 'speedtest' compiles again...
[thirdparty/pdns.git] / pdns / mplexer.hh
CommitLineData
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>
c454d11b 6#include <boost/lexical_cast.hpp>
0bff046b 7#include <vector>
ab3e8a6c
BH
8#include <map>
9#include <stdexcept>
10#include <string>
f14ebffb 11#include "utility.hh"
ab3e8a6c
BH
12
13class FDMultiplexerException : public std::runtime_error
14{
15public:
16 FDMultiplexerException(const std::string& str) : std::runtime_error(str)
17 {}
18};
19
a1dfcec8
BH
20
21/** Very simple FD multiplexer, based on callbacks and boost::any parameters
22 As a special service, this parameter is kept around and can be modified,
23 allowing for state to be stored inside the multiplexer.
24
25 It has some "interesting" semantics
26*/
1f4abb20 27
ab3e8a6c
BH
28class FDMultiplexer
29{
d8f6d49f
BH
30public:
31 // typedef boost::variant<PacketID, TCPConnection> funcparam_t;
32 typedef boost::any funcparam_t;
ab3e8a6c 33protected:
d8f6d49f
BH
34
35 typedef boost::function< void(int, funcparam_t&) > callbackfunc_t;
ab3e8a6c
BH
36 struct Callback
37 {
38 callbackfunc_t d_callback;
d8f6d49f 39 funcparam_t d_parameter;
0bff046b 40 struct timeval d_ttd;
ab3e8a6c
BH
41 };
42
43public:
44 FDMultiplexer() : d_inrun(false)
45 {}
46 virtual ~FDMultiplexer()
47 {}
48
0bff046b 49 virtual int run(struct timeval* tv) = 0;
ab3e8a6c 50
a1dfcec8 51 //! Add an fd to the read watch list - currently an fd can only be on one list at a time!
d8f6d49f 52 virtual void addReadFD(int fd, callbackfunc_t toDo, const funcparam_t& parameter=funcparam_t())
ab3e8a6c 53 {
a1dfcec8 54 this->addFD(d_readCallbacks, fd, toDo, parameter);
ab3e8a6c
BH
55 }
56
a1dfcec8 57 //! Add an fd to the write watch list - currently an fd can only be on one list at a time!
d8f6d49f 58 virtual void addWriteFD(int fd, callbackfunc_t toDo, const funcparam_t& parameter=funcparam_t())
ab3e8a6c 59 {
a1dfcec8 60 this->addFD(d_writeCallbacks, fd, toDo, parameter);
ab3e8a6c
BH
61 }
62
a1dfcec8 63 //! Remove an fd from the read watch list. You can't call this function on an fd that is closed already!
6dcd28c3 64 /** WARNING: references to 'parameter' become invalid after this function! */
ab3e8a6c
BH
65 virtual void removeReadFD(int fd)
66 {
a1dfcec8 67 this->removeFD(d_readCallbacks, fd);
ab3e8a6c
BH
68 }
69
a1dfcec8 70 //! Remove an fd from the write watch list. You can't call this function on an fd that is closed already!
6dcd28c3 71 /** WARNING: references to 'parameter' become invalid after this function! */
a1dfcec8 72 virtual void removeWriteFD(int fd)
ab3e8a6c 73 {
a1dfcec8 74 this->removeFD(d_writeCallbacks, fd);
ab3e8a6c
BH
75 }
76
0bff046b
BH
77 virtual void setReadTTD(int fd, struct timeval tv, int timeout)
78 {
79 if(!d_readCallbacks.count(fd))
80 throw FDMultiplexerException("attempt to timestamp fd not in the multiplexer");
81 tv.tv_sec += timeout;
82 d_readCallbacks[fd].d_ttd=tv;
83 }
84
d8f6d49f 85 virtual funcparam_t& getReadParameter(int fd)
a6ae6414
BH
86 {
87 if(!d_readCallbacks.count(fd))
88 throw FDMultiplexerException("attempt to look up data in multiplexer for unlisted fd "+boost::lexical_cast<std::string>(fd));
89 return d_readCallbacks[fd].d_parameter;
90 }
91
d8f6d49f 92 virtual std::vector<std::pair<int, funcparam_t> > getTimeouts(const struct timeval& tv)
0bff046b 93 {
d8f6d49f 94 std::vector<std::pair<int, funcparam_t> > ret;
0bff046b
BH
95 for(callbackmap_t::iterator i=d_readCallbacks.begin(); i!=d_readCallbacks.end(); ++i)
96 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))
4957a608 97 ret.push_back(std::make_pair(i->first, i->second.d_parameter));
0bff046b
BH
98 return ret;
99 }
100
1f4abb20
BH
101 typedef FDMultiplexer* getMultiplexer_t();
102 typedef std::multimap<int, getMultiplexer_t*> FDMultiplexermap_t;
103
104 static FDMultiplexermap_t& getMultiplexerMap()
105 {
106 static FDMultiplexermap_t theMap;
107 return theMap;
108 }
109
110 virtual std::string getName() = 0;
111
a6ae6414 112
ab3e8a6c
BH
113protected:
114 typedef std::map<int, Callback> callbackmap_t;
115 callbackmap_t d_readCallbacks, d_writeCallbacks;
ab3e8a6c 116
d8f6d49f 117 virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter)=0;
ab3e8a6c
BH
118 virtual void removeFD(callbackmap_t& cbmap, int fd)=0;
119 bool d_inrun;
a1dfcec8 120 callbackmap_t::iterator d_iter;
c454d11b 121
d8f6d49f 122 void accountingAddFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter)
c454d11b
BH
123 {
124 Callback cb;
125 cb.d_callback=toDo;
126 cb.d_parameter=parameter;
127 memset(&cb.d_ttd, 0, sizeof(cb.d_ttd));
128
129 if(cbmap.count(fd))
130 throw FDMultiplexerException("Tried to add fd "+boost::lexical_cast<std::string>(fd)+ " to multiplexer twice");
131 cbmap[fd]=cb;
132 }
133
134 void accountingRemoveFD(callbackmap_t& cbmap, int fd)
135 {
136 if(!cbmap.erase(fd))
137 throw FDMultiplexerException("Tried to remove unlisted fd "+boost::lexical_cast<std::string>(fd)+ " from multiplexer");
138 }
1f4abb20
BH
139};
140
141class SelectFDMultiplexer : public FDMultiplexer
142{
143public:
144 SelectFDMultiplexer()
145 {}
146 virtual ~SelectFDMultiplexer()
147 {}
ab3e8a6c 148
0bff046b 149 virtual int run(struct timeval* tv);
1f4abb20 150
d8f6d49f 151 virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter);
1f4abb20
BH
152 virtual void removeFD(callbackmap_t& cbmap, int fd);
153 std::string getName()
154 {
155 return "select";
156 }
ab3e8a6c
BH
157};
158