summaryrefslogtreecommitdiff
path: root/src/Commons/EventReceiver.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Commons/EventReceiver.h')
-rw-r--r--src/Commons/EventReceiver.h319
1 files changed, 319 insertions, 0 deletions
diff --git a/src/Commons/EventReceiver.h b/src/Commons/EventReceiver.h
new file mode 100644
index 0000000..5fe5514
--- /dev/null
+++ b/src/Commons/EventReceiver.h
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @author Karol Majewski (k.majewski@samsung.com)
+ * @version 0.1
+ * @brief
+ */
+#ifndef WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_
+#define WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_
+
+#include <memory>
+#include <assert.h>
+#include <dpl/event/thread_event_dispatcher.h>
+#include <dpl/event/controller.h>
+#include <dpl/type_list.h>
+#include <dpl/event/abstract_event_call.h>
+#include <dpl/log/wrt_log.h>
+#include <dpl/mutex.h>
+#include <Commons/ThreadPool.h>
+
+namespace WrtDeviceApis {
+namespace Commons {
+template<class TemplateEvent>
+class SignalEventCall : public DPL::Event::AbstractEventCall
+{
+ std::shared_ptr<TemplateEvent> m_event;
+
+ public:
+
+ SignalEventCall(const std::shared_ptr<TemplateEvent> &event) : m_event(event)
+ {}
+ virtual void Call()
+ {
+ WrtLogD("signaling in SignalEventCall");
+ m_event->signalSynchronousEventFlag();
+ }
+};
+
+template<class TemplateEvent>
+class EventReceiver :
+ protected DPL::Event::Controller<
+ typename DPL::TypeListDecl<std::shared_ptr<TemplateEvent> >::Type>
+{
+ DPL::Event::ThreadEventDispatcher m_threadDispatcher;
+
+ protected:
+
+ EventReceiver(ThreadEnum::Enumeration threadType)
+ {
+ DPL::Thread *thread =
+ ThreadPool::getInstance().getThreadRef(threadType);
+ DPL::Event::ControllerEventHandler<std::shared_ptr<TemplateEvent> >::
+ Touch();
+ DPL::Event::ControllerEventHandler<std::shared_ptr<TemplateEvent> >::
+ SwitchToThread(thread);
+ }
+
+ void signalEventByDispatcher(const std::shared_ptr<TemplateEvent> &event)
+ {
+ WrtLogD("called");
+ Try {
+ DPL::Event::AbstractEventDispatcher *dispatcher =
+ ThreadPool::getInstance().getDispatcher(m_threadDispatcher);
+ dispatcher->AddEventCall(new SignalEventCall<TemplateEvent>(event));
+ }
+ Catch(DPL::Thread::Exception::UnmanagedThread) {
+ // if called on unmanaged thread,
+ // call signalSynchronousEventFlag() directly
+ WrtLogE("signalSynchronousEventFlag() is called"
+ "by unmanaged thread");
+ event->signalSynchronousEventFlag();
+ }
+ }
+
+ virtual ~EventReceiver()
+ {
+ DPL::Event::ControllerEventHandler<std::shared_ptr<TemplateEvent> >::
+ SwitchToThread(NULL);
+ }
+};
+
+template<class TemplateEvent>
+class EventRequestReceiver : private EventReceiver<TemplateEvent>
+{
+ public:
+ EventRequestReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
+ TemplateEvent>(threadType)
+ {}
+
+ virtual void OnRequestReceived(const std::shared_ptr<TemplateEvent> &) = 0;
+
+ /*
+ *
+ * @argument delaySeconds - event will be received not sooner than after
+ * delay (in seconds)
+ */
+ void PostRequest(const std::shared_ptr<TemplateEvent> &event,
+ double delaySeconds = 0.0)
+ {
+ WrtLogD("called");
+ {
+ DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
+ assert(TemplateEvent::STATE_INITIAL == event->m_state);
+ event->m_state = TemplateEvent::STATE_REQUEST_SEND;
+ }
+
+ if (TemplateEvent::HANDLING_SYNCHRONOUS == event->getHandlingType() &&
+ !event->m_synchronousEventFlag)
+ {
+ event->m_synchronousEventFlag = new DPL::WaitableEvent();
+ }
+
+ if (0.0 == delaySeconds) {
+ DPL::Event::ControllerEventHandler<std::shared_ptr<TemplateEvent> >
+ ::
+ PostEvent(event);
+ } else {
+ DPL::Event::ControllerEventHandler<std::shared_ptr<TemplateEvent> >
+ ::
+ PostTimedEvent(event, delaySeconds);
+ }
+
+ switch (event->getHandlingType()) {
+ case TemplateEvent::HANDLING_NOT_SET:
+ assert(0);
+ break;
+ case TemplateEvent::HANDLING_SYNCHRONOUS:
+ event->waitForAnswer();
+ break;
+ }
+ }
+
+ void OnEventReceived(const std::shared_ptr<TemplateEvent> &event)
+ {
+ WrtLogD("called");
+ {
+ DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
+ if (event->m_cancelled) {
+ event->handleCancel();
+ event->m_cancelAllowed = true;
+ event->signalCancelStatusFlag();
+ event->signalFinishedFlag();
+ return;
+ } else {
+ assert(
+ TemplateEvent::STATE_REQUEST_SEND == event->m_state &&
+ "Wrong state!");
+ }
+ event->m_state = TemplateEvent::STATE_REQUEST_RECEIVED;
+ }
+
+ OnRequestReceived(event);
+ event->signalCancelStatusFlag();
+ //After Controller ends processing it should call it to signal that work
+ // is done
+ {
+ DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
+
+ if (event->m_cancelled) {
+ //if cancel was not handled in OnRequestReceived when we should
+ //process as if it was not cancelled at all.
+ if (event->m_cancelAllowed) {
+ event->handleCancel();
+ event->signalFinishedFlag();
+ return;
+ }
+ }
+ //when event is not in manual answer mode we will answer now
+ if (TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER !=
+ event->m_handlingType &&
+ TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER !=
+ event->m_handlingType)
+ {
+ event->m_state = TemplateEvent::STATE_ANSWER_SEND;
+ }
+ }
+
+ switch (event->m_handlingType) {
+ case TemplateEvent::HANDLING_NOT_SET:
+ assert(0);
+ break;
+ case TemplateEvent::HANDLING_SYNCHRONOUS:
+ //event->Signal();
+ this->signalEventByDispatcher(event);
+ break;
+ case TemplateEvent::HANDLING_ASYNCHRONOUS:
+ ///TODO check - shouldn't it be in signalEventByDispatcher?
+ if (NULL != event->m_remoteController) {
+ event->m_remoteController->PostAnswer(event);
+ }
+ //event->Signal();
+ this->signalEventByDispatcher(event);
+ break;
+ //when event is in manual answer mode we do nothing - the answer will be
+ // send explicit from the code
+ case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
+ case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
+ break;
+ }
+ }
+
+ virtual void ManualAnswer(const std::shared_ptr<TemplateEvent> &event)
+ {
+ WrtLogD("called");
+ assert(
+ event->m_handlingType ==
+ TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER ||
+ event->m_handlingType ==
+ TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER);
+ {
+ DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
+ if (event->m_cancelled) {
+ //if cancel was not handled in OnRequestReceived when we should
+ //process as if it was not cancelled at all.
+ if (event->m_cancelAllowed) {
+ event->handleCancel();
+ event->signalCancelStatusFlag();
+ event->signalFinishedFlag();
+ return;
+ }
+ }
+ event->m_state = TemplateEvent::STATE_ANSWER_SEND;
+ }
+ switch (event->m_handlingType) {
+ case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
+ //event->Signal();
+ this->signalEventByDispatcher(event);
+ break;
+ case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
+ //event->Signal();
+ if (NULL != event->m_remoteController) {
+ event->m_remoteController->PostAnswer(event);
+ }
+ this->signalEventByDispatcher(event);
+ break;
+ default:
+ break;
+ }
+ }
+};
+
+template<class TemplateEvent>
+class EventAnswerReceiver : private EventReceiver<TemplateEvent>
+{
+ public:
+ EventAnswerReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
+ TemplateEvent>(threadType)
+ {}
+
+ virtual void OnAnswerReceived(const std::shared_ptr<TemplateEvent> &) = 0;
+
+ //it should be hidden outside, but I can't do it! I can't! :|
+ void PostAnswer(const std::shared_ptr<TemplateEvent> &event)
+ {
+ WrtLogD("called");
+ event->signalCancelStatusFlag();
+ DPL::Event::ControllerEventHandler<std::shared_ptr<TemplateEvent> >::
+ PostEvent(
+ event);
+ }
+
+ void OnEventReceived(const std::shared_ptr<TemplateEvent> &event)
+ {
+ WrtLogD("EventAnswerReceiver: answer received");
+ //check if it can be processed and set the state
+ {
+ DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
+
+ //in case someone changed it to synchronous call, we don't process
+ // it
+ if (TemplateEvent::STATE_CHANGED_TO_SYNCHRONOUS ==
+ event->m_state || TemplateEvent::STATE_ENDED ==
+ event->m_state)
+ {
+ return;
+ }
+ //we should get cancelled or answer_send state here
+ assert(
+ TemplateEvent::STATE_ANSWER_SEND == event->m_state &&
+ "Wrong state!");
+
+ if (event->m_cancelled && event->m_cancelAllowed) {
+ event->handleCancel();
+ event->signalFinishedFlag();
+ return;
+ }
+ event->m_state = TemplateEvent::STATE_ANSWER_RECEIVED;
+ }
+
+ OnAnswerReceived(event);
+
+ {
+ DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
+ assert(TemplateEvent::STATE_ANSWER_RECEIVED == event->m_state);
+ event->m_state = TemplateEvent::STATE_ENDED;
+ delete event->m_cancelStatusFlag;
+ event->m_cancelStatusFlag = NULL;
+ //if someone is waiting
+ event->signalFinishedFlag();
+ }
+ }
+};
+}
+} // WrtDeviceApisCommon
+
+#endif /* WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_ */