/** * \file * * \author Georg Hopp * * \copyright * Copyright © 2014 Georg Hopp * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "trbase.h" #include "trdata.h" #include "trhash.h" #include "tr/event.h" #include "tr/event_subject.h" #include "tr/event_dispatcher.h" int ZERO = 0; void TR_eventDispatcherStart(TR_EventDispatcher this) { this->running = 1; while (this->running || (! TR_queueEmpty(this->events))) { struct timespec tp; int now; // milliseconds TR_Event event; TR_Queue handler_queue; TR_HashValue handler_queue_hv; clock_gettime(CLOCK_REALTIME, &tp); now = tp.tv_sec * 1000 + tp.tv_nsec / 1000000; if (this->nextbeat && this->nextbeat <= now) { this->nextbeat += this->heartbeat; TR_eventDispatcherEnqueueEvent( this, TR_eventSubjectEmit( (TR_EventSubject)this, TR_DISPATCHER_EVENT_HEARTBEAT, NULL)); } if (TR_queueEmpty(this->events) || this->nextpoll <= now) { int evtid = TR_EVD_CLIENT == this->mode ? TR_DISPATCHER_EVENT_USER_WAIT : TR_DISPATCHER_EVENT_DATA_WAIT; int * toutptr = TR_queueEmpty(this->events) ? NULL : &ZERO; this->nextpoll += this->pollinterval; event = TR_eventSubjectEmit((TR_EventSubject)this, evtid, toutptr); } else { event = TR_queueGet(this->events); } handler_queue_hv = TR_hashGetByVal( this->handler, TR_sdbm( (unsigned char *)&(event->id), sizeof(event->id))); handler_queue = handler_queue_hv ? *(TR_Queue *)handler_queue_hv->value : NULL; if (handler_queue && ! TR_queueEmpty(handler_queue)) { TR_Queue queue_node = handler_queue->first; TR_EventDone done = TR_EVENT_PENDING; while (queue_node) { TR_EventHandler handler = queue_node->msg; TR_EventDone this_done; this_done = TR_eventHandlerHandleEvent(handler, event); done = TR_EVENT_DONE == done ? done : this_done; queue_node = queue_node->next; } if (TR_EVENT_DONE == done) { TR_delete(event); } else { TR_eventDispatcherEnqueueEvent(this, event); } } } } // vim: set ts=4 sw=4: