dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / scd / scd_sock_poller.cpp
1 #include "scd_sock_poller.h"
2
3 #include <algorithm>
4 #include <errno.h>
5 #include <string>
6 #include <string.h>
7
8 #include "scd_exception.h"
9 #include "scd_logging.h"
10
11
12 bool scd_sock_poller::register_handler(scd_sock_ev_handler_if& handler,
13         sock_ev events)
14 {
15     // can not register the same handler twice
16     if (_handler_exists(handler))
17     {
18         scd_warn("socket handler already registered while registering");
19         return false;
20     }
21     
22     // register handler
23     _handlers.push_back(&handler);
24
25     // register socket and events
26     struct pollfd fd;
27     fd.fd = handler.get_sock()._socket;
28     fd.events = events;
29     _events.push_back(fd);
30     return true;
31
32 } // register_handler()
33
34
35 bool scd_sock_poller::remove_handler(const scd_sock_ev_handler_if &handler)
36 {
37     int idx = _get_index(handler);
38     
39     // check if handler was found
40     if (idx == -1)
41     {
42         scd_warn("socket handler not registered while removing poll handler");
43         return false;
44     }
45
46     // remove events and handler from vectors
47     _events.erase(_events.begin() + idx);
48     _handlers.erase(_handlers.begin() + idx);
49
50     return true;
51
52 } // remove_handler()
53
54
55 bool scd_sock_poller::set_ev(const scd_sock_ev_handler_if &handler,
56         sock_ev events)
57 {
58     int idx = _get_index(handler);
59
60     if (idx == -1)
61     {
62         scd_warn("socket handler not registered while setting poll events");
63         return false;
64     }
65
66     _events[idx].events = events;
67
68     return true;
69 } // set_ev()
70
71
72 bool scd_sock_poller::get_ev(const scd_sock_ev_handler_if &handler,
73         sock_ev &events) const
74 {
75     int idx = _get_index(handler);
76
77     if (idx == -1)
78     {
79         scd_warn("socket handler not registered while getting poll events");
80         return false;
81     }
82
83     events = _events[idx].events;
84
85     return true;
86
87 } // get_ev()
88
89
90 bool scd_sock_poller::wait(int ms)
91 {
92     int ret = _poll(ms);
93     if (ret > 0)
94         return true;
95     else
96         return false;
97 }
98
99
100 bool scd_sock_poller::process()
101 {
102     int ret = _poll(0);
103
104     if (ret != 0) // events occured
105     {
106         _callback();
107         return true;
108     }
109     else
110         return false;
111
112 } // process()
113
114
115 void scd_sock_poller::wait_process()
116 {
117     _poll(-1);
118     _callback();
119
120 } // wait_process()
121
122
123 bool scd_sock_poller::_handler_exists(const scd_sock_ev_handler_if &handler)
124     const
125 {
126     std::vector<scd_sock_ev_handler_if*>::const_iterator iter;
127
128     iter = std::find(_handlers.begin(), _handlers.end(), &handler);
129
130     if (iter == _handlers.end())
131         return false;
132     else
133         return true;
134
135 } // _handler_exists()
136
137
138 int scd_sock_poller::_get_index(const scd_sock_ev_handler_if &handler) const
139 {
140     std::vector<scd_sock_ev_handler_if*>::const_iterator iter;
141
142     iter = std::find(_handlers.begin(), _handlers.end(), &handler);
143
144     if (iter == _handlers.end())
145     {
146         // handler not found
147         return -1;
148     }
149     else
150     {
151         // return index (random access iterator)
152         return iter - _handlers.begin();
153     }
154
155 } // _get_index()
156
157
158 int scd_sock_poller::_poll(int ms)
159 {
160     int ret;
161
162     if (ms < 0 && _events.size() == 0)
163     {
164         scd_debug("immediately returning form infinite poll: no events to watch");
165         return 0;
166     }
167
168     do
169     {
170         ret = poll(&_events[0], _events.size(), ms);
171         if (ret == -1 && errno != EINTR)
172         {
173             std::string error("poll(): ");
174             error += std::string(strerror(errno));
175             throw scd_exception(error);
176         }
177     }
178     while (ret == -1 && errno == EINTR);
179
180     return ret;
181
182 } // _poll()
183
184
185 void scd_sock_poller::_callback()
186 {
187     /* called handlers might remove themselves. as the order
188      * should not break we operate on copies here */
189     std::vector<pollfd> events_cpy = _events;
190     std::vector<scd_sock_ev_handler_if*> handlers_cpy = _handlers;
191
192     // for all handlers
193     for (int i=0; i<events_cpy.size(); i++)
194     {
195         if (events_cpy[i].events & events_cpy[i].revents)
196         {
197             // this event occured => callback handler
198             handlers_cpy[i]->handle_sock_ev(events_cpy[i].revents);
199         }
200     } // for all events
201 } // _callback()