From fbaa8ccbbd31a3fa1ae262d608e6e310851a4882 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 12:26:37 +0100 Subject: [PATCH 1/5] Add convenience function to supply a EventDataRef to Event::signal() --- telldus-core/common/Event.cpp | 6 +++++- telldus-core/common/Event.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/Event.cpp b/telldus-core/common/Event.cpp index 40dbea8d..7cb30558 100644 --- a/telldus-core/common/Event.cpp +++ b/telldus-core/common/Event.cpp @@ -61,9 +61,13 @@ void EventBase::signal() { } void EventBase::signal(EventData *eventData) { + this->signal(EventDataRef(eventData)); +} + +void EventBase::signal(EventDataRef eventData) { { TelldusCore::MutexLocker locker(&d->mutex); - d->eventDataList.push_back(EventDataRef(eventData)); + d->eventDataList.push_back(eventData); } sendSignal(); } diff --git a/telldus-core/common/Event.h b/telldus-core/common/Event.h index 6d662d89..2482b99d 100644 --- a/telldus-core/common/Event.h +++ b/telldus-core/common/Event.h @@ -42,6 +42,7 @@ namespace TelldusCore { bool isSignaled(); void signal(); virtual void signal(EventData *eventData); + void signal(EventDataRef eventData); EventDataRef takeSignal(); protected: From f7336b34f91142026ecf8a4f647effe8595ae6b0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 11:45:19 +0100 Subject: [PATCH 2/5] Rewrite our callback dispatcher. Instead of dynamically create new threads for each callback they are now precreated when they are registered. Each callback will now be called using the same thread each time. --- telldus-core/client/CallbackDispatcher.cpp | 158 +++++++++++++----- telldus-core/client/CallbackDispatcher.h | 60 +++++-- .../client/CallbackMainDispatcher.cpp | 108 ++++-------- telldus-core/client/CallbackMainDispatcher.h | 10 +- telldus-core/client/Client.cpp | 11 +- 5 files changed, 197 insertions(+), 150 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 2cae6ebb..d27ac5cd 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -8,64 +8,136 @@ */ #include "client/CallbackDispatcher.h" +#include "common/Event.h" +#include "common/EventHandler.h" namespace TelldusCore { -TDEventDispatcher::TDEventDispatcher(EventDataRef cbd, CallbackStruct *cb, EventRef cbDone) - :Thread(), doneRunning(false), callbackData(cbd), callback(cb), callbackExecuted(cbDone) { - this->startAndLock(&callback->mutex); +class TDEventDispatcher::PrivateData { +public: + EventHandler eventHandler; + EventRef stopEvent, callbackEvent; + int id; + void *func, *context; +}; + +TDEventDispatcher::TDEventDispatcher(int id, void *func, void *context) //EventDataRef cbd, CallbackStruct *cb, EventRef cbDone) + :Thread() { + d = new PrivateData; + d->stopEvent = d->eventHandler.addEvent(); + d->callbackEvent = d->eventHandler.addEvent(); + d->id = id; + d->func = func; + d->context = context; + this->start(); } TDEventDispatcher::~TDEventDispatcher() { + printf("Stopping dispatcher\n"); + d->stopEvent->signal(); this->wait(); + delete d; } -bool TDEventDispatcher::done() const { - return doneRunning; +int TDEventDispatcher::id() const { + return d->id; +} + +void TDEventDispatcher::queue(EventDataRef eventData) { + d->callbackEvent->signal(eventData); } void TDEventDispatcher::run() { - this->fireEvent(); - doneRunning = true; - callbackExecuted->signal(); -} - -void TDEventDispatcher::fireEvent() { - if (callback->type == CallbackStruct::DeviceEvent) { - DeviceEventCallbackData *data = dynamic_cast(callbackData.get()); - if (!data) { - return; + while (true) { + d->eventHandler.waitForAny(); + if (d->stopEvent->isSignaled()) { + break; } - ((TDDeviceEvent)callback->event)(data->deviceId, data->deviceState, data->deviceStateValue.c_str(), callback->id, callback->context); - - } else if (callback->type == CallbackStruct::DeviceChangeEvent) { - DeviceChangeEventCallbackData *data = dynamic_cast(callbackData.get()); - if (!data) { - return; + if (d->callbackEvent->isSignaled()) { + TelldusCore::EventDataRef eventData = d->callbackEvent->takeSignal(); + this->execute(eventData); } - ((TDDeviceChangeEvent)callback->event)(data->deviceId, data->changeEvent, data->changeType, callback->id, callback->context); - - } else if (callback->type == CallbackStruct::RawDeviceEvent) { - RawDeviceEventCallbackData *data = dynamic_cast(callbackData.get()); - if (!data) { - return; - } - ((TDRawDeviceEvent)callback->event)(data->data.c_str(), data->controllerId, callback->id, callback->context); - - } else if (callback->type == CallbackStruct::SensorEvent) { - SensorEventCallbackData *data = dynamic_cast(callbackData.get()); - if (!data) { - return; - } - ((TDSensorEvent)callback->event)(data->protocol.c_str(), data->model.c_str(), data->id, data->dataType, data->value.c_str(), data->timestamp, callback->id, callback->context); - - } else if (callback->type == CallbackStruct::ControllerEvent) { - ControllerEventCallbackData *data = dynamic_cast(callbackData.get()); - if (!data) { - return; - } - ((TDControllerEvent)callback->event)(data->controllerId, data->changeEvent, data->changeType, data->newValue.c_str(), callback->id, callback->context); } } +TDDeviceEventDispatcher::TDDeviceEventDispatcher(int id, void *func, void *context) + :TDEventDispatcher(id, func, context) +{} + +void TDDeviceEventDispatcher::execute(EventDataRef eventData) { + DeviceEventCallbackData *data = dynamic_cast(eventData.get()); + if (!data) { + return; + } + ((TDDeviceEvent)d->func)(data->deviceId, data->deviceState, data->deviceStateValue.c_str(), d->id, d->context); +} + +CallbackStruct::CallbackType TDDeviceEventDispatcher::type() { + return CallbackStruct::DeviceEvent; +} + +TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(int id, void *func, void *context) + :TDEventDispatcher(id, func, context) +{} + +void TDDeviceChangeEventDispatcher::execute(EventDataRef eventData) { + DeviceChangeEventCallbackData *data = dynamic_cast(eventData.get()); + if (!data) { + return; + } + ((TDDeviceChangeEvent)d->func)(data->deviceId, data->changeEvent, data->changeType, d->id, d->context); +} + +CallbackStruct::CallbackType TDDeviceChangeEventDispatcher::type() { + return CallbackStruct::DeviceChangeEvent; +} + +TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher(int id, void *func, void *context) + :TDEventDispatcher(id, func, context) +{} + +void TDRawDeviceEventDispatcher::execute(EventDataRef eventData) { + RawDeviceEventCallbackData *data = dynamic_cast(eventData.get()); + if (!data) { + return; + } + ((TDRawDeviceEvent)d->func)(data->data.c_str(), data->controllerId, d->id, d->context); +} + +CallbackStruct::CallbackType TDRawDeviceEventDispatcher::type() { + return CallbackStruct::RawDeviceEvent; +} + +TDSensorEventDispatcher::TDSensorEventDispatcher(int id, void *func, void *context) + :TDEventDispatcher(id, func, context) +{} + +void TDSensorEventDispatcher::execute(EventDataRef eventData) { + SensorEventCallbackData *data = dynamic_cast(eventData.get()); + if (!data) { + return; + } + ((TDSensorEvent)d->func)(data->protocol.c_str(), data->model.c_str(), data->id, data->dataType, data->value.c_str(), data->timestamp, d->id, d->context); +} + +CallbackStruct::CallbackType TDSensorEventDispatcher::type() { + return CallbackStruct::SensorEvent; +} + +TDControllerEventDispatcher::TDControllerEventDispatcher(int id, void *func, void *context) + :TDEventDispatcher(id, func, context) +{} + +void TDControllerEventDispatcher::execute(EventDataRef eventData) { + ControllerEventCallbackData *data = dynamic_cast(eventData.get()); + if (!data) { + return; + } + ((TDControllerEvent)d->func)(data->controllerId, data->changeEvent, data->changeType, data->newValue.c_str(), d->id, d->context); +} + +CallbackStruct::CallbackType TDControllerEventDispatcher::type() { + return CallbackStruct::ControllerEvent; +} + } // namespace TelldusCore diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index ee2b11f0..4b387906 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -19,12 +19,6 @@ namespace TelldusCore { - /*template struct CallbackStruct { - T event; - int id; - void *context; - TelldusCore::Mutex mutex; - };*/ struct CallbackStruct { enum CallbackType { DeviceEvent, DeviceChangeEvent, RawDeviceEvent, SensorEvent, ControllerEvent }; CallbackType type; @@ -33,9 +27,6 @@ namespace TelldusCore { void *context; TelldusCore::Mutex mutex; }; - /*typedef CallbackStruct DeviceChangeEvent; - typedef CallbackStruct RawDeviceEvent; - typedef CallbackStruct SensorEvent;*/ class CallbackData: public EventDataBase { public: @@ -86,17 +77,52 @@ namespace TelldusCore { class TDEventDispatcher : public Thread { public: - TDEventDispatcher(EventDataRef callbackData, CallbackStruct *callback, TelldusCore::EventRef cbDone); + TDEventDispatcher(int id, void *func, void *context); virtual ~TDEventDispatcher(); - bool done() const; + int id() const; + void queue(EventDataRef eventData); + virtual CallbackStruct::CallbackType type() = 0; protected: + class PrivateData; + PrivateData *d; + virtual void run(); - bool doneRunning; - private: - void fireEvent(); - EventDataRef callbackData; - CallbackStruct *callback; - EventRef callbackExecuted; + virtual void execute(EventDataRef eventData) = 0; + }; + class TDDeviceEventDispatcher : public TDEventDispatcher { + public: + TDDeviceEventDispatcher(int id, void *func, void *context); + virtual CallbackStruct::CallbackType type(); + protected: + virtual void execute(EventDataRef eventData); + }; + class TDDeviceChangeEventDispatcher : public TDEventDispatcher { + public: + TDDeviceChangeEventDispatcher(int id, void *func, void *context); + virtual CallbackStruct::CallbackType type(); + protected: + virtual void execute(EventDataRef eventData); + }; + class TDRawDeviceEventDispatcher : public TDEventDispatcher { + public: + TDRawDeviceEventDispatcher(int id, void *func, void *context); + virtual CallbackStruct::CallbackType type(); + protected: + virtual void execute(EventDataRef eventData); + }; + class TDSensorEventDispatcher : public TDEventDispatcher { + public: + TDSensorEventDispatcher(int id, void *func, void *context); + virtual CallbackStruct::CallbackType type(); + protected: + virtual void execute(EventDataRef eventData); + }; + class TDControllerEventDispatcher : public TDEventDispatcher { + public: + TDControllerEventDispatcher(int id, void *func, void *context); + virtual CallbackStruct::CallbackType type(); + protected: + virtual void execute(EventDataRef eventData); }; } diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index 585c65b0..5b495449 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -13,52 +13,60 @@ namespace TelldusCore { -typedef std::list CallbackList; +typedef std::list CallbackList; class CallbackMainDispatcher::PrivateData { public: - EventHandler eventHandler; - EventRef stopEvent, generalCallbackEvent, janitor; - Mutex mutex; - std::list > eventThreadList; - CallbackList callbackList; - int lastCallbackId; }; -CallbackMainDispatcher::CallbackMainDispatcher() -:Thread() { +CallbackMainDispatcher::CallbackMainDispatcher() { d = new PrivateData; - d->stopEvent = d->eventHandler.addEvent(); - d->generalCallbackEvent = d->eventHandler.addEvent(); - d->janitor = d->eventHandler.addEvent(); // Used for cleanups - d->lastCallbackId = 0; } CallbackMainDispatcher::~CallbackMainDispatcher(void) { - d->stopEvent->signal(); - wait(); { - MutexLocker locker(&d->mutex); + TelldusCore::MutexLocker locker(&d->mutex); + for(CallbackList::iterator it = d->callbackList.begin(); it != d->callbackList.end(); ++it) { + delete (*it); + } } delete d; } -EventRef CallbackMainDispatcher::retrieveCallbackEvent() { - return d->generalCallbackEvent; +void CallbackMainDispatcher::execute(CallbackStruct::CallbackType type, EventData *eventData) { + { + TelldusCore::MutexLocker locker(&d->mutex); + EventDataRef eventDataRef(eventData); + for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { + if ( (*callback_it)->type() != type ) { + continue; + } + (*callback_it)->queue(eventDataRef); + } + } } int CallbackMainDispatcher::registerCallback(CallbackStruct::CallbackType type, void *eventFunction, void *context) { TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; - CallbackStruct *callback = new CallbackStruct; - callback->type = type; - callback->event = eventFunction; - callback->id = id; - callback->context = context; + TelldusCore::TDEventDispatcher *callback; + if (type == CallbackStruct::DeviceEvent) { + callback = new TelldusCore::TDDeviceEventDispatcher(id, eventFunction, context); + } else if (type == CallbackStruct::DeviceChangeEvent) { + callback = new TelldusCore::TDDeviceChangeEventDispatcher(id, eventFunction, context); + } else if (type == CallbackStruct::RawDeviceEvent) { + callback = new TelldusCore::TDRawDeviceEventDispatcher(id, eventFunction, context); + } else if (type == CallbackStruct::SensorEvent) { + callback = new TelldusCore::TDSensorEventDispatcher(id, eventFunction, context); + } else if (type == CallbackStruct::ControllerEvent) { + callback = new TelldusCore::TDControllerEventDispatcher(id, eventFunction, context); + } else { + return -1; + } d->callbackList.push_back(callback); return id; } @@ -68,7 +76,7 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { { TelldusCore::MutexLocker locker(&d->mutex); for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { - if ( (*callback_it)->id != callbackId ) { + if ( (*callback_it)->id() != callbackId ) { continue; } newEventList.splice(newEventList.begin(), d->callbackList, callback_it); @@ -77,9 +85,6 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { } if (newEventList.size()) { CallbackList::iterator it = newEventList.begin(); - { // Lock and unlock to make sure no one else uses the object - TelldusCore::MutexLocker locker( &(*it)->mutex ); - } delete (*it); newEventList.erase(it); return TELLSTICK_SUCCESS; @@ -87,53 +92,4 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { return TELLSTICK_ERROR_NOT_FOUND; } -void CallbackMainDispatcher::run() { - while(!d->stopEvent->isSignaled()) { - if (!d->eventHandler.waitForAny()) { - continue; - } - - if(d->generalCallbackEvent->isSignaled()) { - EventDataRef eventData = d->generalCallbackEvent->takeSignal(); - - CallbackData *cbd = dynamic_cast(eventData.get()); - if (!cbd) { - continue; - } - TelldusCore::MutexLocker locker(&d->mutex); - for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { - if ( (*callback_it)->type == cbd->type ) { - std::tr1::shared_ptr ptr(new TelldusCore::TDEventDispatcher(eventData, *callback_it, d->janitor)); - d->eventThreadList.push_back(ptr); - } - } - } - if (d->janitor->isSignaled()) { - // Clear all of them if there is more than one - while(d->janitor->isSignaled()) { - d->janitor->popSignal(); - } - this->cleanupCallbacks(); - } - } -} - -void CallbackMainDispatcher::cleanupCallbacks() { - bool again = false; - - // Device Event - do { - again = false; - MutexLocker locker(&d->mutex); - std::list >::iterator it = d->eventThreadList.begin(); - for (; it != d->eventThreadList.end(); ++it) { - if ((*it)->done()) { - d->eventThreadList.erase(it); - again = true; - break; - } - } - } while (again); -} - } // namespace TelldusCore diff --git a/telldus-core/client/CallbackMainDispatcher.h b/telldus-core/client/CallbackMainDispatcher.h index 764780e3..911d21a4 100644 --- a/telldus-core/client/CallbackMainDispatcher.h +++ b/telldus-core/client/CallbackMainDispatcher.h @@ -12,29 +12,23 @@ #include "client/CallbackDispatcher.h" #include "common/Thread.h" -#include "common/Event.h" -#include "common/EventHandler.h" namespace TelldusCore { - class CallbackMainDispatcher : public Thread + class CallbackMainDispatcher { public: CallbackMainDispatcher(void); ~CallbackMainDispatcher(void); - EventRef retrieveCallbackEvent(); + void execute(TelldusCore::CallbackStruct::CallbackType type, EventData *eventData); int registerCallback( TelldusCore::CallbackStruct::CallbackType type, void *eventFunction, void *context ); int unregisterCallback( int callbackId ); - protected: - void run(); - private: class PrivateData; PrivateData *d; - void cleanupCallbacks(void); }; } diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index cf4e5e33..3cd095ce 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -33,7 +33,6 @@ Client::Client() d->running = true; d->sensorCached = false; d->controllerCached = false; - d->callbackMainDispatcher.start(); start(); } @@ -105,20 +104,20 @@ void Client::run() { data->deviceId = Message::takeInt(&clientMessage); data->changeEvent = Message::takeInt(&clientMessage); data->changeType = Message::takeInt(&clientMessage); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + d->callbackMainDispatcher.execute(CallbackStruct::DeviceChangeEvent, data); } else if(type == L"TDDeviceEvent") { DeviceEventCallbackData *data = new DeviceEventCallbackData(); data->deviceId = Message::takeInt(&clientMessage); data->deviceState = Message::takeInt(&clientMessage); data->deviceStateValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + d->callbackMainDispatcher.execute(CallbackStruct::DeviceEvent, data); } else if(type == L"TDRawDeviceEvent") { RawDeviceEventCallbackData *data = new RawDeviceEventCallbackData(); data->data = TelldusCore::wideToString(Message::takeString(&clientMessage)); data->controllerId = Message::takeInt(&clientMessage); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + d->callbackMainDispatcher.execute(CallbackStruct::RawDeviceEvent, data); } else if(type == L"TDSensorEvent") { SensorEventCallbackData *data = new SensorEventCallbackData(); @@ -128,7 +127,7 @@ void Client::run() { data->dataType = Message::takeInt(&clientMessage); data->value = TelldusCore::wideToString(Message::takeString(&clientMessage)); data->timestamp = Message::takeInt(&clientMessage); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + d->callbackMainDispatcher.execute(CallbackStruct::SensorEvent, data); } else if(type == L"TDControllerEvent") { ControllerEventCallbackData *data = new ControllerEventCallbackData(); @@ -136,7 +135,7 @@ void Client::run() { data->changeEvent = Message::takeInt(&clientMessage); data->changeType = Message::takeInt(&clientMessage); data->newValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + d->callbackMainDispatcher.execute(CallbackStruct::ControllerEvent, data); } else { clientMessage = L""; // cleanup, if message contained garbage/unhandled data From 25542e7f90b3bcf4d3ae2be0b1d7795bc63fa3c8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 14:09:15 +0100 Subject: [PATCH 3/5] Remove old code --- telldus-core/client/CallbackDispatcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index d27ac5cd..ae9e1722 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -21,7 +21,7 @@ public: void *func, *context; }; -TDEventDispatcher::TDEventDispatcher(int id, void *func, void *context) //EventDataRef cbd, CallbackStruct *cb, EventRef cbDone) +TDEventDispatcher::TDEventDispatcher(int id, void *func, void *context) :Thread() { d = new PrivateData; d->stopEvent = d->eventHandler.addEvent(); From 4d366f483eccc817378be5cd95926ef49b4c5151 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 14:12:29 +0100 Subject: [PATCH 4/5] Remove debug code --- telldus-core/client/CallbackDispatcher.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index ae9e1722..99c9a6a7 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -33,7 +33,6 @@ TDEventDispatcher::TDEventDispatcher(int id, void *func, void *context) } TDEventDispatcher::~TDEventDispatcher() { - printf("Stopping dispatcher\n"); d->stopEvent->signal(); this->wait(); delete d; From 6842c248185c840d7eab6bc1f37b12e1b66eb3d4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 14:12:47 +0100 Subject: [PATCH 5/5] Made the loop a bit smaller --- telldus-core/client/CallbackDispatcher.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 99c9a6a7..a1f72263 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -47,11 +47,8 @@ void TDEventDispatcher::queue(EventDataRef eventData) { } void TDEventDispatcher::run() { - while (true) { + while (!d->stopEvent->isSignaled()) { d->eventHandler.waitForAny(); - if (d->stopEvent->isSignaled()) { - break; - } if (d->callbackEvent->isSignaled()) { TelldusCore::EventDataRef eventData = d->callbackEvent->takeSignal(); this->execute(eventData);