16 #include <sys/types.h>
18 #include <sys/select.h>
26 #include <sys/resource.h>
30 #include "rofl/common/cmemory.h"
31 #include "rofl/common/logging.h"
32 #include "rofl/common/croflexception.h"
33 #include "rofl/common/thread_helper.h"
34 #include "rofl/common/cpipe.h"
35 #include "rofl/common/cevents.h"
36 #include "rofl/common/ctimers.h"
37 #include "rofl/common/ctimer.h"
61 if (cioloop::threads.find(tid) == cioloop::threads.end()) {
62 cioloop::threads[tid] =
new cioloop(tid);
64 return *(cioloop::threads[tid]);
72 if (cioloop::threads.find(tid) == cioloop::threads.end()) {
75 delete cioloop::threads[tid];
76 cioloop::threads.erase(tid);
94 if (cioloop::threads.find(tid) == cioloop::threads.end()) {
97 cioloop::threads[tid]->keep_on_running =
false;
99 RwLock lock(rfds_rwlock, RwLock::RWLOCK_WRITE);
103 RwLock lock(wfds_rwlock, RwLock::RWLOCK_WRITE);
107 RwLock lock(events_rwlock, RwLock::RWLOCK_WRITE);
111 RwLock lock(timers_rwlock, RwLock::RWLOCK_WRITE);
114 if (tid != pthread_self()) {
124 for (std::map<pthread_t, cioloop*>::iterator
125 it = cioloop::threads.begin(); it != cioloop::threads.end(); ++it) {
128 cioloop::threads.clear();
135 get_tid()
const {
return tid; };
145 add_readfd(ciosrv* iosrv,
int fd) {
146 RwLock lock(rfds_rwlock, RwLock::RWLOCK_WRITE);
149 minrfd = (minrfd > (
unsigned int)(fd+0)) ? (
unsigned int)(fd+0) : minrfd;
150 maxrfd = (maxrfd < (
unsigned int)(fd+1)) ? (
unsigned int)(fd+1) : maxrfd;
152 if (tid != pthread_self()) {
161 drop_readfd(ciosrv* iosrv,
int fd) {
162 RwLock lock(rfds_rwlock, RwLock::RWLOCK_WRITE);
165 if (minrfd == (
unsigned int)(fd+0)) {
166 minrfd = rfds.size();
167 for (
unsigned int i = fd + 1; i < rfds.size(); i++) {
168 if (rfds[i] != NULL) {
175 if (maxrfd == (
unsigned int)(fd+1)) {
177 for (
unsigned int i = fd; i > 0; i--) {
178 if (rfds[i] != NULL) {
185 if (tid != pthread_self()) {
194 add_writefd(ciosrv* iosrv,
int fd) {
195 RwLock lock(wfds_rwlock, RwLock::RWLOCK_WRITE);
198 minwfd = (minwfd > (
unsigned int)(fd+0)) ? (
unsigned int)(fd+0) : minwfd;
199 maxwfd = (maxwfd < (
unsigned int)(fd+1)) ? (
unsigned int)(fd+1) : maxwfd;
201 if (tid != pthread_self()) {
210 drop_writefd(ciosrv* iosrv,
int fd) {
211 RwLock lock(wfds_rwlock, RwLock::RWLOCK_WRITE);
214 if (minwfd == (
unsigned int)(fd+0)) {
215 minwfd = wfds.size();
216 for (
unsigned int i = fd + 1; i < wfds.size(); i++) {
217 if (wfds[i] != NULL) {
224 if (maxwfd == (
unsigned int)(fd+1)) {
226 for (
unsigned int i = fd; i > 0; i--) {
227 if (wfds[i] != NULL) {
234 if (tid != pthread_self()) {
243 has_timer(ciosrv* iosrv) {
244 RwLock lock(timers_rwlock, RwLock::RWLOCK_WRITE);
245 timers[iosrv] =
true;
246 if (tid != pthread_self()) {
255 has_no_timer(ciosrv *iosrv) {
256 RwLock lock(timers_rwlock, RwLock::RWLOCK_WRITE);
257 timers[iosrv] =
false;
264 has_event(ciosrv* iosrv) {
265 RwLock lock(events_rwlock, RwLock::RWLOCK_WRITE);
266 events[iosrv] =
true;
267 if (tid != pthread_self()) {
276 has_no_event(ciosrv* iosrv) {
277 RwLock lock(events_rwlock, RwLock::RWLOCK_WRITE);
278 events[iosrv] =
false;
286 cioloop(pthread_t tid = 0) :
288 keep_on_running(false) {
291 this->tid = pthread_self();
295 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
296 throw eSysCall(
"getrlimit()");
298 RwLock rlock(rfds_rwlock, RwLock::RWLOCK_WRITE);
299 RwLock wlock(wfds_rwlock, RwLock::RWLOCK_WRITE);
300 for (
unsigned int i = 0; i < rlim.rlim_cur; i++) {
301 rfds.push_back(NULL);
302 wfds.push_back(NULL);
304 minrfd = rfds.size();
306 minwfd = wfds.size();
319 cioloop(cioloop
const& t) {
327 operator= (cioloop
const& t) {
345 child_sig_handler (
int x);
352 operator<< (std::ostream& os, cioloop
const& ioloop) {
353 os << indent(0) <<
"<cioloop tid:0x"
354 << std::hex << ioloop.get_tid() << std::dec <<
">" << std::endl;
357 RwLock lock(ioloop.rfds_rwlock, RwLock::RWLOCK_READ);
358 os << indent(2) <<
"<read-fds: ";
359 for (
unsigned int i = 0; i < ioloop.rfds.size(); ++i) {
360 if (NULL != ioloop.rfds.at(i)) {
364 os <<
">" << std::endl;
368 RwLock lock(ioloop.wfds_rwlock, RwLock::RWLOCK_READ);
369 os << indent(2) <<
"<write-fds: ";
370 for (
unsigned int i = 0; i < ioloop.wfds.size(); ++i) {
371 if (NULL != ioloop.wfds.at(i)) {
375 os <<
">" << std::endl;
379 RwLock lock(ioloop.timers_rwlock, RwLock::RWLOCK_READ);
380 os << indent(2) <<
"<instances with timer needs: ";
382 for (std::map<ciosrv*, bool>::const_iterator
383 it = ioloop.timers.begin(); it != ioloop.timers.end(); ++it) {
384 os << it->first <<
":" << it->second <<
" ";
386 os <<
">" << std::endl;
390 RwLock lock(ioloop.events_rwlock, RwLock::RWLOCK_READ);
391 os << indent(2) <<
"<instances with event needs: ";
393 for (std::map<ciosrv*, bool>::const_iterator
394 it = ioloop.events.begin(); it != ioloop.events.end(); ++it) {
395 os << it->first <<
":" << it->second <<
" ";
397 os <<
">" << std::endl;
405 static PthreadRwLock threads_rwlock;
406 static std::map<pthread_t, cioloop*> threads;
408 std::vector<ciosrv*> rfds;
409 mutable PthreadRwLock rfds_rwlock;
410 std::vector<ciosrv*> wfds;
411 mutable PthreadRwLock wfds_rwlock;
412 std::map<ciosrv*, bool> timers;
413 mutable PthreadRwLock timers_rwlock;
414 std::map<ciosrv*, bool> events;
415 mutable PthreadRwLock events_rwlock;
419 bool keep_on_running;
497 ciosrv(pthread_t tid = 0);
514 operator= (
const ciosrv& iosrv);
530 events.add_event(event);
717 return timers.
reset(timer_id, timespec);
750 return timers.
pending(timer_id);
801 __handle_revent(
int fd) {
804 }
catch (eEventsNotFound& e) {}
814 logging::trace <<
"[rofl-common][ciosrv][handle-timeout] timer: " << std::endl << timer;
816 }
catch (eTimersNotFound& e) {}
822 operator<< (std::ostream& os,
const ciosrv& iosvc) {
823 os << indent(0) <<
"<ciosrv >" << std::endl;
824 os << indent(2) <<
"<rfds: ";
825 for (std::set<int>::const_iterator it = iosvc.rfds.begin(); it != iosvc.rfds.end(); ++it) {
828 os <<
">" << std::endl;
829 os << indent(2) <<
"<wfds: ";
830 for (std::set<int>::const_iterator it = iosvc.wfds.begin(); it != iosvc.wfds.end(); ++it) {
833 os <<
">" << std::endl;
835 { indent i(2); os << iosvc.timers; }
836 { indent i(2); os << iosvc.events; }
842 static PthreadRwLock ciolist_rwlock;
843 static std::set<ciosrv*> ciolist;
const rofl::ctimerid & reset(const rofl::ctimerid &timer_id, const rofl::ctimespec ×pec)
Resets an existing timer identifier by its handle with a new timeout value.
Definition: ctimers.h:134
void cancel_timer(const rofl::ctimerid &timer_id)
Cancels a pending timer.
Definition: ciosrv.h:759
void clear()
Removes all timers from this timer list.
Definition: ctimers.h:214
void deregister_filedesc_w(int fd)
Deregisters a file descriptor from write events.
Definition: ciosrv.h:667
void stop()
Terminates cioloop instance running in thread identified by this->tid.
Definition: ciosrv.h:93
pthread_t get_thread_id() const
Returns thread-id of local thread.
Definition: ciosrv.h:540
Timer handle used by class rofl::cioloop.
Definition: ctimerid.h:21
void shutdown()
Terminates all running cioloop instances.
Definition: ciosrv.h:123
void register_filedesc_r(int fd)
Registers a file descriptor for read events.
Definition: ciosrv.h:632
void notify(const cevent &event)
Sends a notification to this ciosrv instance.
Definition: ciosrv.h:529
void cancel_all_events()
Cancels all pending events of this instance.
Definition: ciosrv.h:780
Single timer object in rofl-common.
Definition: ctimer.h:45
Environment expected by an instance of class rofl::ctimer.
Definition: ctimer.h:27
static cioloop & get_loop(pthread_t tid=0)
Returns reference to cioloop instance identified by thread id or if none is specified, cioloop of local thread.
Definition: ciosrv.h:57
virtual ~ciosrv()
Deallocates resources for this ciosrv object.
Definition: ciosrv.cc:46
void cancel_all_timers()
Cancels all pending timers of this instance.
Definition: ciosrv.h:770
void register_filedesc_w(int fd)
Registers a file descriptor for write events.
Definition: ciosrv.h:656
void cancel(const ctimerid &timer_id)
Removes a timer identified by the given timer handle from this timer list.
Definition: ctimers.h:200
virtual void handle_event(const rofl::cevent &event)
Handler for event notifications using cevent instances.
Definition: ciosrv.h:564
const rofl::ctimerid & reset_timer(const rofl::ctimerid &timer_id, const rofl::ctimespec ×pec)
Resets a running timer of type opaque.
Definition: ciosrv.h:714
virtual void handle_timeout(int opaque, void *data=(void *) 0)
Handler for timer events.
Definition: ciosrv.h:611
rofl::ctimer get_expired_timer()
Returns the next timer from timer list, when it has already expired.
Definition: ctimers.h:157
bool empty()
Deletes all timers in this timer list.
Definition: ctimers.h:88
const rofl::ctimerid & add_timer(const rofl::ctimer &t)
Inserts a new timer into the timer list.
Definition: ctimers.h:114
bool pending(const rofl::ctimerid &timer_id)
Checks whether a certain timer identified by the given handle is still pending.
Definition: ctimers.h:184
const rofl::ctimerid & register_timer(int opaque, const rofl::ctimespec ×pec)
Installs a new timer to fire in t seconds.
Definition: ciosrv.h:698
virtual void handle_revent(int fd)
Handler for read events on file descriptors.
Definition: ciosrv.h:576
Definition: thread_helper.h:88
bool pending_timer(const rofl::ctimerid &timer_id)
Checks for a pending timer of type opaque.
Definition: ciosrv.h:749
Single event used internally by class crofl::cioloop.
Definition: cevent.h:20
ciosrv(pthread_t tid=0)
Initializes all structures for this ciosrv object.
Definition: ciosrv.cc:31
ctimerid & restart_timer(rofl::ctimerid &timer_id, int opaque, const rofl::ctimespec ×pec)
Resets an existing or creates a new timer.
Definition: ciosrv.h:733
Defines an IO service loop for a single thread.
Definition: ciosrv.h:49
Base class for IO services.
Definition: ciosrv.h:491
Time specification used by class rofl::ctimer object.
Definition: ctimespec.h:25
rofl::ctimer get_next_timer()
Returns a copy of the next expiring timer in this timer list.
Definition: ctimers.h:99
static void drop_loop(pthread_t tid)
Drop.
Definition: ciosrv.h:71
void deregister_filedesc_r(int fd)
Deregisters a file descriptor from read events.
Definition: ciosrv.h:643
virtual void handle_xevent(int fd)
Handler for exceptions on file descriptors.
Definition: ciosrv.h:599
virtual void handle_wevent(int fd)
Handler for write events on file descriptors.
Definition: ciosrv.h:588