summaryrefslogtreecommitdiff
path: root/src/Commons/IEvent.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Commons/IEvent.h')
-rw-r--r--src/Commons/IEvent.h385
1 files changed, 385 insertions, 0 deletions
diff --git a/src/Commons/IEvent.h b/src/Commons/IEvent.h
new file mode 100644
index 0000000..3c29590
--- /dev/null
+++ b/src/Commons/IEvent.h
@@ -0,0 +1,385 @@
+/*
+ * 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_IEVENT_H_
+#define WRTDEVICEAPIS_COMMONS_IEVENT_H_
+
+#include <memory>
+
+#include <assert.h>
+#include <dpl/log/wrt_log.h>
+#include <dpl/event/controller.h>
+#include <dpl/mutex.h>
+#include <Commons/Exception.h>
+#include <Commons/EventReceiver.h>
+
+namespace WrtDeviceApis {
+namespace Commons {
+class IEventPrivateData
+{
+ public:
+ virtual ~IEventPrivateData()
+ {}
+};
+
+class IEventController
+{
+ std::shared_ptr<IEventPrivateData> m_privateData;
+
+ public:
+ virtual void waitTillProcessed() = 0;
+ virtual void waitForAnswer() = 0;
+ virtual bool cancelRequest()
+ {
+ return false;
+ }
+ virtual bool changeCallToSynchronous() = 0;
+ virtual ~IEventController()
+ {}
+
+ void setPrivateData(
+ const std::shared_ptr<IEventPrivateData> &privateData)
+ {
+ m_privateData = privateData;
+ }
+ const std::shared_ptr<IEventPrivateData>& getPrivateData()
+ {
+ return m_privateData;
+ }
+};
+typedef std::shared_ptr<IEventController> IEventControllerPtr;
+
+// CRTP pattern
+template<class Super>
+class IEvent : /*private DPL::WaitableEvent, */ public IEventController
+{
+ public:
+ friend class EventRequestReceiver<Super>;
+ friend class EventAnswerReceiver<Super>;
+ friend class SignalEventCall<Super>;
+ friend class EventReceiver<Super>;
+
+ enum HandlingType
+ {
+ HANDLING_NOT_SET = -1,
+ HANDLING_SYNCHRONOUS = 0,
+ HANDLING_ASYNCHRONOUS = 1,
+ HANDLING_SYNCHRONOUS_MANUAL_ANSWER = 2,
+ HANDLING_ASYNCHRONOUS_MANUAL_ANSWER = 3
+ };
+
+ enum State
+ {
+ STATE_INITIAL,
+ STATE_REQUEST_SEND,
+ STATE_REQUEST_RECEIVED,
+ STATE_ANSWER_SEND,
+ STATE_ANSWER_RECEIVED,
+ STATE_ENDED,
+ STATE_CHANGED_TO_SYNCHRONOUS
+ };
+
+ private:
+ void handleCancel()
+ {
+ clearOnCancel();
+ m_state = STATE_ENDED;
+ m_exceptionCode = Commons::ExceptionCodes::EventCancelledException;
+ //if someone is waiting
+ signalSynchronousEventFlag();
+ }
+
+ protected:
+ DPL::Mutex m_stateMutex;
+ State m_state;
+ HandlingType m_handlingType;
+ EventAnswerReceiver< Super > *m_remoteController;
+ Commons::ExceptionCodes::Enumeration m_exceptionCode;
+ DPL::WaitableEvent *m_synchronousEventFlag;
+ DPL::WaitableEvent *m_finishedFlag;
+ DPL::WaitableEvent *m_cancelStatusFlag;
+ bool m_cancelSignalAhead;
+ bool m_cancelled;
+ bool m_cancelAllowed;
+
+ IEvent() :
+ m_state(STATE_INITIAL),
+ m_handlingType(HANDLING_NOT_SET),
+ m_remoteController(NULL),
+ m_exceptionCode(Commons::ExceptionCodes::None),
+ m_synchronousEventFlag(NULL),
+ m_finishedFlag(NULL),
+ m_cancelStatusFlag(NULL),
+ m_cancelSignalAhead(false),
+ m_cancelled(false),
+ m_cancelAllowed(false)
+ {}
+
+ virtual void waitForAnswer()
+ {
+ assert(HANDLING_SYNCHRONOUS == m_handlingType);
+ DPL::WaitForSingleHandle(m_synchronousEventFlag->GetHandle());
+ {
+ DPL::Mutex::ScopedLock lock(&m_stateMutex);
+ m_state = STATE_ENDED;
+ }
+ signalFinishedFlag();
+ WrtLogD("deleting m_processEvent");
+ delete m_synchronousEventFlag;
+ m_synchronousEventFlag = NULL;
+ }
+
+ void signalFinishedFlag()
+ {
+ if (m_finishedFlag) {
+ m_finishedFlag->Signal();
+ }
+ }
+
+ DPL::WaitableEvent &getFinishedFlag()
+ {
+ if (!m_finishedFlag) {
+ m_finishedFlag = new DPL::WaitableEvent();
+ }
+ return *m_finishedFlag;
+ }
+
+ void signalCancelStatusFlag()
+ {
+ WrtLogD("signaling cancel");
+ DPL::Mutex::ScopedLock lock(&m_stateMutex);
+ m_cancelSignalAhead = true;
+ if (m_cancelStatusFlag) {
+ m_cancelStatusFlag->Signal();
+ }
+ }
+
+ DPL::WaitableEvent &getCancelStatusFlag()
+ {
+ if (!m_cancelStatusFlag) {
+ m_cancelStatusFlag = new DPL::WaitableEvent();
+ }
+ return *m_cancelStatusFlag;
+ }
+
+ void signalSynchronousEventFlag()
+ {
+ if (m_synchronousEventFlag) {
+ m_synchronousEventFlag->Signal();
+ }
+ }
+
+ public:
+
+ /*
+ * Gets the answer receiver pointer.
+ */
+ EventAnswerReceiver< Super > * getAnswerReceiverRef() const
+ {
+ return m_remoteController;
+ }
+
+ virtual ~IEvent()
+ {
+ delete m_cancelStatusFlag;
+ delete m_finishedFlag;
+ delete m_synchronousEventFlag;
+ }
+
+ virtual bool changeCallToSynchronous()
+ {
+ return setForSynchronousCall();
+ }
+
+ virtual void waitTillProcessed()
+ {
+ DPL::WaitForSingleHandle(getFinishedFlag().GetHandle());
+ delete m_finishedFlag;
+ m_finishedFlag = NULL;
+ }
+
+ virtual void clearOnCancel()
+ {}
+
+ Commons::ExceptionCodes::Enumeration getExceptionCode() const
+ {
+ return m_exceptionCode;
+ }
+ void setExceptionCode(Commons::ExceptionCodes::Enumeration exceptionCode)
+ {
+ m_exceptionCode = exceptionCode;
+ }
+
+ short getHandlingType() const
+ {
+ return m_handlingType;
+ }
+
+ virtual bool setForSynchronousCall()
+ {
+ DPL::Mutex::ScopedLock lock(&m_stateMutex);
+ if (m_cancelled) {
+ return false;
+ }
+ switch (m_state) {
+ case STATE_ANSWER_SEND:
+ m_state = STATE_CHANGED_TO_SYNCHRONOUS;
+ break;
+ case STATE_ANSWER_RECEIVED:
+ case STATE_ENDED:
+ return false;
+ default:
+ break;
+ }
+ m_handlingType = HANDLING_SYNCHRONOUS;
+ return true;
+ }
+
+ virtual bool setForAsynchronousCall(
+ EventAnswerReceiver< Super > *remoteController)
+ {
+ DPL::Mutex::ScopedLock lock(&m_stateMutex);
+ if (m_cancelled) {
+ return false;
+ }
+ switch (m_state) {
+ case STATE_ANSWER_SEND:
+ case STATE_ANSWER_RECEIVED:
+ case STATE_ENDED:
+ return false;
+ default:
+ break;
+ }
+ m_handlingType = HANDLING_ASYNCHRONOUS;
+ m_remoteController = remoteController;
+ return true;
+ }
+
+ /*
+ * Normally, after invoking OnRequestReceived in RequestReceiver, the answer
+ * is being send automatically (after flow leaves OnRequestReceived).
+ * After calling this function, the answer is not being send automatically,
+ * you need to call ManualAnswer to send event back.
+ * It works both in asynchronous and synchronous handling type.
+ */
+ virtual bool switchToManualAnswer()
+ {
+ assert(
+ m_handlingType == HANDLING_ASYNCHRONOUS || m_handlingType ==
+ HANDLING_SYNCHRONOUS);
+
+ DPL::Mutex::ScopedLock lock(&m_stateMutex);
+ if (m_cancelled) {
+ return false;
+ }
+ switch (m_state) {
+ case STATE_ANSWER_SEND:
+ case STATE_ANSWER_RECEIVED:
+ case STATE_ENDED:
+ return false;
+ default:
+ break;
+ }
+
+ switch (m_handlingType) {
+ case HANDLING_ASYNCHRONOUS:
+ m_handlingType = HANDLING_ASYNCHRONOUS_MANUAL_ANSWER;
+ break;
+ case HANDLING_SYNCHRONOUS:
+ m_handlingType = HANDLING_SYNCHRONOUS_MANUAL_ANSWER;
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+
+ bool checkCancelled()
+ {
+ //DPL::Mutex::ScopedLock lock(&m_stateMutex);
+ return m_cancelled;
+ }
+
+ void tryCancelled()
+ {
+ //DPL::Mutex::ScopedLock lock(&m_stateMutex);
+ if (m_cancelled) {
+ Throw(Commons::EventCancelledException);
+ }
+ }
+
+ bool getCancelAllowed() const
+ {
+ return m_cancelAllowed;
+ }
+
+ void setCancelAllowed(bool cancelAllowed)
+ {
+ m_cancelAllowed = cancelAllowed;
+ }
+
+ bool cancelRequest()
+ {
+ WrtLogD("trying to cancel");
+ assert(HANDLING_ASYNCHRONOUS == m_handlingType ||
+ HANDLING_ASYNCHRONOUS_MANUAL_ANSWER == m_handlingType);
+ bool signaled = false;
+ {
+ DPL::Mutex::ScopedLock lock(&m_stateMutex);
+ if (m_cancelled) {
+ return false;
+ }
+ switch (m_state) {
+ case STATE_INITIAL:
+ assert(0);
+ case STATE_ANSWER_SEND:
+ WrtLogD("cancelling");
+ m_cancelled = true;
+ delete m_cancelStatusFlag;
+ m_cancelStatusFlag = NULL;
+ return m_cancelAllowed;
+ case STATE_ANSWER_RECEIVED:
+ case STATE_ENDED:
+ return false;
+ default:
+ break;
+ }
+ WrtLogD("cancelling");
+ m_cancelled = true;
+ signaled = m_cancelSignalAhead;
+ if (!signaled) {
+ //create waitable handle
+ getCancelStatusFlag();
+ }
+ }
+ WrtLogD("waiting for cancel flag");
+ if (!signaled) {
+ DPL::WaitForSingleHandle(getCancelStatusFlag().GetHandle());
+ }
+ delete m_cancelStatusFlag;
+ m_cancelStatusFlag = NULL;
+ return m_cancelAllowed;
+ }
+};
+}
+} // WrtDeviceApisCommon
+
+#endif /* WRTDEVICEAPIS_COMMONS_IEVENT_H_ */