+#include "scd_sock_poller.h"
+
+#include <algorithm>
+#include <errno.h>
+#include <string>
+#include <string.h>
+
+#include "scd_exception.h"
+#include "scd_logging.h"
+
+
+bool scd_sock_poller::register_handler(scd_sock_ev_handler_if& handler,
+ sock_ev events)
+{
+ // can not register the same handler twice
+ if (_handler_exists(handler))
+ {
+ scd_warn("socket handler already registered while registering");
+ return false;
+ }
+
+ // register handler
+ _handlers.push_back(&handler);
+
+ // register socket and events
+ struct pollfd fd;
+ fd.fd = handler.get_sock()._socket;
+ fd.events = events;
+ _events.push_back(fd);
+ return true;
+
+} // register_handler()
+
+
+bool scd_sock_poller::remove_handler(const scd_sock_ev_handler_if &handler)
+{
+ int idx = _get_index(handler);
+
+ // check if handler was found
+ if (idx == -1)
+ {
+ scd_warn("socket handler not registered while removing poll handler");
+ return false;
+ }
+
+ // remove events and handler from vectors
+ _events.erase(_events.begin() + idx);
+ _handlers.erase(_handlers.begin() + idx);
+
+ return true;
+
+} // remove_handler()
+
+
+bool scd_sock_poller::set_ev(const scd_sock_ev_handler_if &handler,
+ sock_ev events)
+{
+ int idx = _get_index(handler);
+
+ if (idx == -1)
+ {
+ scd_warn("socket handler not registered while setting poll events");
+ return false;
+ }
+
+ _events[idx].events = events;
+
+ return true;
+} // set_ev()
+
+
+bool scd_sock_poller::get_ev(const scd_sock_ev_handler_if &handler,
+ sock_ev &events) const
+{
+ int idx = _get_index(handler);
+
+ if (idx == -1)
+ {
+ scd_warn("socket handler not registered while getting poll events");
+ return false;
+ }
+
+ events = _events[idx].events;
+
+ return true;
+
+} // get_ev()
+
+
+bool scd_sock_poller::wait(int ms)
+{
+ int ret = _poll(ms);
+ if (ret > 0)
+ return true;
+ else
+ return false;
+}
+
+
+bool scd_sock_poller::process()
+{
+ int ret = _poll(0);
+
+ if (ret != 0) // events occured
+ {
+ _callback();
+ return true;
+ }
+ else
+ return false;
+
+} // process()
+
+
+void scd_sock_poller::wait_process()
+{
+ _poll(-1);
+ _callback();
+
+} // wait_process()
+
+
+bool scd_sock_poller::_handler_exists(const scd_sock_ev_handler_if &handler)
+ const
+{
+ std::vector<scd_sock_ev_handler_if*>::const_iterator iter;
+
+ iter = std::find(_handlers.begin(), _handlers.end(), &handler);
+
+ if (iter == _handlers.end())
+ return false;
+ else
+ return true;
+
+} // _handler_exists()
+
+
+int scd_sock_poller::_get_index(const scd_sock_ev_handler_if &handler) const
+{
+ std::vector<scd_sock_ev_handler_if*>::const_iterator iter;
+
+ iter = std::find(_handlers.begin(), _handlers.end(), &handler);
+
+ if (iter == _handlers.end())
+ {
+ // handler not found
+ return -1;
+ }
+ else
+ {
+ // return index (random access iterator)
+ return iter - _handlers.begin();
+ }
+
+} // _get_index()
+
+
+int scd_sock_poller::_poll(int ms)
+{
+ int ret;
+
+ if (ms < 0 && _events.size() == 0)
+ {
+ scd_debug("immediately returning form infinite poll: no events to watch");
+ return 0;
+ }
+
+ do
+ {
+ ret = poll(&_events[0], _events.size(), ms);
+ if (ret == -1 && errno != EINTR)
+ {
+ std::string error("poll(): ");
+ error += std::string(strerror(errno));
+ throw scd_exception(error);
+ }
+ }
+ while (ret == -1 && errno == EINTR);
+
+ return ret;
+
+} // _poll()
+
+
+void scd_sock_poller::_callback()
+{
+ /* called handlers might remove themselves. as the order
+ * should not break we operate on copies here */
+ std::vector<pollfd> events_cpy = _events;
+ std::vector<scd_sock_ev_handler_if*> handlers_cpy = _handlers;
+
+ // for all handlers
+ for (int i=0; i<events_cpy.size(); i++)
+ {
+ if (events_cpy[i].events & events_cpy[i].revents)
+ {
+ // this event occured => callback handler
+ handlers_cpy[i]->handle_sock_ev(events_cpy[i].revents);
+ }
+ } // for all events
+} // _callback()