Initialize Tizen 2.3
[framework/web/wrt-plugins-common.git] / src_wearable / Commons / IEvent.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @author      Karol Majewski (k.majewski@samsung.com)
18  * @version     0.1
19  * @brief
20  */
21
22 #ifndef WRTDEVICEAPIS_COMMONS_IEVENT_H_
23 #define WRTDEVICEAPIS_COMMONS_IEVENT_H_
24
25 #include <assert.h>
26 #include <dpl/event/controller.h>
27 #include <dpl/mutex.h>
28 #include <dpl/shared_ptr.h>
29 #include <Commons/Exception.h>
30 #include <Commons/EventReceiver.h>
31
32 namespace WrtDeviceApis {
33 namespace Commons {
34 class IEventPrivateData
35 {
36   public:
37     virtual ~IEventPrivateData()
38     {}
39 };
40
41 class IEventController
42 {
43     DPL::SharedPtr<IEventPrivateData> m_privateData;
44
45   public:
46     virtual void waitTillProcessed() = 0;
47     virtual void waitForAnswer() = 0;
48     virtual bool cancelRequest()
49     {
50         return false;
51     }
52     virtual bool changeCallToSynchronous() = 0;
53     virtual ~IEventController()
54     {}
55
56     void setPrivateData(
57         const DPL::SharedPtr<IEventPrivateData> &privateData)
58     {
59         m_privateData = privateData;
60     }
61     const DPL::SharedPtr<IEventPrivateData>& getPrivateData()
62     {
63         return m_privateData;
64     }
65 };
66 typedef DPL::SharedPtr<IEventController> IEventControllerPtr;
67
68 // CRTP pattern
69 template<class Super>
70 class IEvent : /*private DPL::WaitableEvent, */ public IEventController
71 {
72   public:
73     friend class EventRequestReceiver<Super>;
74     friend class EventAnswerReceiver<Super>;
75     friend class SignalEventCall<Super>;
76     friend class EventReceiver<Super>;
77
78     enum HandlingType
79     {
80         HANDLING_NOT_SET = -1,
81         HANDLING_SYNCHRONOUS = 0,
82         HANDLING_ASYNCHRONOUS = 1,
83         HANDLING_SYNCHRONOUS_MANUAL_ANSWER = 2,
84         HANDLING_ASYNCHRONOUS_MANUAL_ANSWER = 3
85     };
86
87     enum State
88     {
89         STATE_INITIAL,
90         STATE_REQUEST_SEND,
91         STATE_REQUEST_RECEIVED,
92         STATE_ANSWER_SEND,
93         STATE_ANSWER_RECEIVED,
94         STATE_ENDED,
95         STATE_CHANGED_TO_SYNCHRONOUS
96     };
97
98   private:
99     void handleCancel()
100     {
101         clearOnCancel();
102         m_state = STATE_ENDED;
103         m_exceptionCode = Commons::ExceptionCodes::EventCancelledException;
104         //if someone is waiting
105         signalSynchronousEventFlag();
106     }
107
108   protected:
109     DPL::Mutex m_stateMutex;
110     State m_state;
111     HandlingType m_handlingType;
112     EventAnswerReceiver< Super > *m_remoteController;
113     Commons::ExceptionCodes::Enumeration m_exceptionCode;
114     DPL::WaitableEvent *m_synchronousEventFlag;
115     DPL::WaitableEvent *m_finishedFlag;
116     DPL::WaitableEvent *m_cancelStatusFlag;
117     bool m_cancelSignalAhead;
118     bool m_cancelled;
119     bool m_cancelAllowed;
120
121     IEvent() :
122         m_state(STATE_INITIAL),
123         m_handlingType(HANDLING_NOT_SET),
124         m_remoteController(NULL),
125         m_exceptionCode(Commons::ExceptionCodes::None),
126         m_synchronousEventFlag(NULL),
127         m_finishedFlag(NULL),
128         m_cancelStatusFlag(NULL),
129         m_cancelSignalAhead(false),
130         m_cancelled(false),
131         m_cancelAllowed(false)
132     {}
133
134     virtual void waitForAnswer()
135     {
136         assert(HANDLING_SYNCHRONOUS == m_handlingType);
137         DPL::WaitForSingleHandle(m_synchronousEventFlag->GetHandle());
138         {
139             DPL::Mutex::ScopedLock lock(&m_stateMutex);
140             m_state = STATE_ENDED;
141         }
142         signalFinishedFlag();
143         LogDebug("deleting m_processEvent");
144         delete m_synchronousEventFlag;
145         m_synchronousEventFlag = NULL;
146     }
147
148     void signalFinishedFlag()
149     {
150         if (m_finishedFlag) {
151             m_finishedFlag->Signal();
152         }
153     }
154
155     DPL::WaitableEvent &getFinishedFlag()
156     {
157         if (!m_finishedFlag) {
158             m_finishedFlag = new DPL::WaitableEvent();
159         }
160         return *m_finishedFlag;
161     }
162
163     void signalCancelStatusFlag()
164     {
165         LogDebug("signaling cancel");
166         DPL::Mutex::ScopedLock lock(&m_stateMutex);
167         m_cancelSignalAhead = true;
168         if (m_cancelStatusFlag) {
169             m_cancelStatusFlag->Signal();
170         }
171     }
172
173     DPL::WaitableEvent &getCancelStatusFlag()
174     {
175         if (!m_cancelStatusFlag) {
176             m_cancelStatusFlag = new DPL::WaitableEvent();
177         }
178         return *m_cancelStatusFlag;
179     }
180
181     void signalSynchronousEventFlag()
182     {
183         if (m_synchronousEventFlag) {
184             m_synchronousEventFlag->Signal();
185         }
186     }
187
188   public:
189
190     /*
191      * Gets the answer receiver pointer.
192      */
193     EventAnswerReceiver< Super > * getAnswerReceiverRef() const
194     {
195         return m_remoteController;
196     }
197
198     virtual ~IEvent()
199     {
200         delete m_cancelStatusFlag;
201         delete m_finishedFlag;
202         delete m_synchronousEventFlag;
203     }
204
205     virtual bool changeCallToSynchronous()
206     {
207         return setForSynchronousCall();
208     }
209
210     virtual void waitTillProcessed()
211     {
212         DPL::WaitForSingleHandle(getFinishedFlag().GetHandle());
213         delete m_finishedFlag;
214         m_finishedFlag = NULL;
215     }
216
217     virtual void clearOnCancel()
218     {}
219
220     Commons::ExceptionCodes::Enumeration getExceptionCode() const
221     {
222         return m_exceptionCode;
223     }
224     void setExceptionCode(Commons::ExceptionCodes::Enumeration exceptionCode)
225     {
226         m_exceptionCode = exceptionCode;
227     }
228
229     short getHandlingType() const
230     {
231         return m_handlingType;
232     }
233
234     virtual bool setForSynchronousCall()
235     {
236         DPL::Mutex::ScopedLock lock(&m_stateMutex);
237         if (m_cancelled) {
238             return false;
239         }
240         switch (m_state) {
241         case STATE_ANSWER_SEND:
242             m_state = STATE_CHANGED_TO_SYNCHRONOUS;
243             break;
244         case STATE_ANSWER_RECEIVED:
245         case STATE_ENDED:
246             return false;
247         default:
248             break;
249         }
250         m_handlingType = HANDLING_SYNCHRONOUS;
251         return true;
252     }
253
254     virtual bool setForAsynchronousCall(
255         EventAnswerReceiver< Super > *remoteController)
256     {
257         DPL::Mutex::ScopedLock lock(&m_stateMutex);
258         if (m_cancelled) {
259             return false;
260         }
261         switch (m_state) {
262         case STATE_ANSWER_SEND:
263         case STATE_ANSWER_RECEIVED:
264         case STATE_ENDED:
265             return false;
266         default:
267             break;
268         }
269         m_handlingType = HANDLING_ASYNCHRONOUS;
270         m_remoteController = remoteController;
271         return true;
272     }
273
274     /*
275      * Normally, after invoking OnRequestReceived in RequestReceiver, the answer
276      * is being send automatically (after flow leaves OnRequestReceived).
277      * After calling this function, the answer is not being send automatically,
278      * you need to call ManualAnswer to send event back.
279      * It works both in asynchronous and synchronous handling type.
280      */
281     virtual bool switchToManualAnswer()
282     {
283         assert(
284             m_handlingType == HANDLING_ASYNCHRONOUS || m_handlingType ==
285             HANDLING_SYNCHRONOUS);
286
287         DPL::Mutex::ScopedLock lock(&m_stateMutex);
288         if (m_cancelled) {
289             return false;
290         }
291         switch (m_state) {
292         case STATE_ANSWER_SEND:
293         case STATE_ANSWER_RECEIVED:
294         case STATE_ENDED:
295             return false;
296         default:
297             break;
298         }
299
300         switch (m_handlingType) {
301         case HANDLING_ASYNCHRONOUS:
302             m_handlingType = HANDLING_ASYNCHRONOUS_MANUAL_ANSWER;
303             break;
304         case HANDLING_SYNCHRONOUS:
305             m_handlingType = HANDLING_SYNCHRONOUS_MANUAL_ANSWER;
306             break;
307         default:
308             break;
309         }
310         return true;
311     }
312
313     bool checkCancelled()
314     {
315         //DPL::Mutex::ScopedLock lock(&m_stateMutex);
316         return m_cancelled;
317     }
318
319     void tryCancelled()
320     {
321         //DPL::Mutex::ScopedLock lock(&m_stateMutex);
322         if (m_cancelled) {
323             Throw(Commons::EventCancelledException);
324         }
325     }
326
327     bool getCancelAllowed() const
328     {
329         return m_cancelAllowed;
330     }
331
332     void setCancelAllowed(bool cancelAllowed)
333     {
334         m_cancelAllowed = cancelAllowed;
335     }
336
337     bool cancelRequest()
338     {
339         LogDebug("trying to cancel");
340         assert(HANDLING_ASYNCHRONOUS == m_handlingType ||
341                HANDLING_ASYNCHRONOUS_MANUAL_ANSWER == m_handlingType);
342         bool signaled = false;
343         {
344             DPL::Mutex::ScopedLock lock(&m_stateMutex);
345             if (m_cancelled) {
346                 return false;
347             }
348             switch (m_state) {
349             case STATE_INITIAL:
350                 assert(0);
351             case STATE_ANSWER_SEND:
352                 LogDebug("cancelling");
353                 m_cancelled = true;
354                 delete m_cancelStatusFlag;
355                 m_cancelStatusFlag = NULL;
356                 return m_cancelAllowed;
357             case STATE_ANSWER_RECEIVED:
358             case STATE_ENDED:
359                 return false;
360             default:
361                 break;
362             }
363             LogDebug("cancelling");
364             m_cancelled = true;
365             signaled = m_cancelSignalAhead;
366             if (!signaled) {
367                 //create waitable handle
368                 getCancelStatusFlag();
369             }
370         }
371         LogDebug("waiting for cancel flag");
372         if (!signaled) {
373             DPL::WaitForSingleHandle(getCancelStatusFlag().GetHandle());
374         }
375         delete m_cancelStatusFlag;
376         m_cancelStatusFlag = NULL;
377         return m_cancelAllowed;
378     }
379 };
380 }
381 } // WrtDeviceApisCommon
382
383 #endif /* WRTDEVICEAPIS_COMMONS_IEVENT_H_ */