[Release] wrt-plugins-common_0.3.82
[framework/web/wrt-plugins-common.git] / src / 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_cancelled;
118     bool m_cancelAllowed;
119
120     IEvent() :
121         m_state(STATE_INITIAL),
122         m_handlingType(HANDLING_NOT_SET),
123         m_remoteController(NULL),
124         m_exceptionCode(Commons::ExceptionCodes::None),
125         m_synchronousEventFlag(NULL),
126         m_finishedFlag(NULL),
127         m_cancelStatusFlag(NULL),
128         m_cancelled(false),
129         m_cancelAllowed(false)
130     {}
131
132     virtual void waitForAnswer()
133     {
134         assert(HANDLING_SYNCHRONOUS == m_handlingType);
135         DPL::WaitForSingleHandle(m_synchronousEventFlag->GetHandle());
136         {
137             DPL::Mutex::ScopedLock lock(&m_stateMutex);
138             m_state = STATE_ENDED;
139         }
140         signalFinishedFlag();
141         LogDebug("deleting m_processEvent");
142         delete m_synchronousEventFlag;
143         m_synchronousEventFlag = NULL;
144     }
145
146     void signalFinishedFlag()
147     {
148         if (m_finishedFlag) {
149             m_finishedFlag->Signal();
150         }
151     }
152
153     DPL::WaitableEvent &getFinishedFlag()
154     {
155         if (!m_finishedFlag) {
156             m_finishedFlag = new DPL::WaitableEvent();
157         }
158         return *m_finishedFlag;
159     }
160
161     void signalCancelStatusFlag()
162     {
163         LogDebug("signaling cancel");
164         if (m_cancelStatusFlag) {
165             m_cancelStatusFlag->Signal();
166         }
167     }
168
169     DPL::WaitableEvent &getCancelStatusFlag()
170     {
171         if (!m_cancelStatusFlag) {
172             m_cancelStatusFlag = new DPL::WaitableEvent();
173         }
174         return *m_cancelStatusFlag;
175     }
176
177     void signalSynchronousEventFlag()
178     {
179         if (m_synchronousEventFlag) {
180             m_synchronousEventFlag->Signal();
181         }
182     }
183
184   public:
185
186     /*
187      * Gets the answer receiver pointer.
188      */
189     EventAnswerReceiver< Super > * getAnswerReceiverRef() const
190     {
191         return m_remoteController;
192     }
193
194     virtual ~IEvent()
195     {
196         delete m_cancelStatusFlag;
197         delete m_finishedFlag;
198         delete m_synchronousEventFlag;
199     }
200
201     virtual bool changeCallToSynchronous()
202     {
203         return setForSynchronousCall();
204     }
205
206     virtual void waitTillProcessed()
207     {
208         DPL::WaitForSingleHandle(getFinishedFlag().GetHandle());
209         delete m_finishedFlag;
210         m_finishedFlag = NULL;
211     }
212
213     virtual void clearOnCancel()
214     {}
215
216     Commons::ExceptionCodes::Enumeration getExceptionCode() const
217     {
218         return m_exceptionCode;
219     }
220     void setExceptionCode(Commons::ExceptionCodes::Enumeration exceptionCode)
221     {
222         m_exceptionCode = exceptionCode;
223     }
224
225     short getHandlingType() const
226     {
227         return m_handlingType;
228     }
229
230     virtual bool setForSynchronousCall()
231     {
232         DPL::Mutex::ScopedLock lock(&m_stateMutex);
233         if (m_cancelled) {
234             return false;
235         }
236         switch (m_state) {
237         case STATE_ANSWER_SEND:
238             m_state = STATE_CHANGED_TO_SYNCHRONOUS;
239             break;
240         case STATE_ANSWER_RECEIVED:
241         case STATE_ENDED:
242             return false;
243         default:
244             break;
245         }
246         m_handlingType = HANDLING_SYNCHRONOUS;
247         return true;
248     }
249
250     virtual bool setForAsynchronousCall(
251         EventAnswerReceiver< Super > *remoteController)
252     {
253         DPL::Mutex::ScopedLock lock(&m_stateMutex);
254         if (m_cancelled) {
255             return false;
256         }
257         switch (m_state) {
258         case STATE_ANSWER_SEND:
259         case STATE_ANSWER_RECEIVED:
260         case STATE_ENDED:
261             return false;
262         default:
263             break;
264         }
265         m_handlingType = HANDLING_ASYNCHRONOUS;
266         m_remoteController = remoteController;
267         return true;
268     }
269
270     /*
271      * Normally, after invoking OnRequestReceived in RequestReceiver, the answer
272      * is being send automatically (after flow leaves OnRequestReceived).
273      * After calling this function, the answer is not being send automatically,
274      * you need to call ManualAnswer to send event back.
275      * It works both in asynchronous and synchronous handling type.
276      */
277     virtual bool switchToManualAnswer()
278     {
279         assert(
280             m_handlingType == HANDLING_ASYNCHRONOUS || m_handlingType ==
281             HANDLING_SYNCHRONOUS);
282
283         DPL::Mutex::ScopedLock lock(&m_stateMutex);
284         if (m_cancelled) {
285             return false;
286         }
287         switch (m_state) {
288         case STATE_ANSWER_SEND:
289         case STATE_ANSWER_RECEIVED:
290         case STATE_ENDED:
291             return false;
292         default:
293             break;
294         }
295
296         switch (m_handlingType) {
297         case HANDLING_ASYNCHRONOUS:
298             m_handlingType = HANDLING_ASYNCHRONOUS_MANUAL_ANSWER;
299             break;
300         case HANDLING_SYNCHRONOUS:
301             m_handlingType = HANDLING_SYNCHRONOUS_MANUAL_ANSWER;
302             break;
303         default:
304             break;
305         }
306         return true;
307     }
308
309     bool checkCancelled()
310     {
311         //DPL::Mutex::ScopedLock lock(&m_stateMutex);
312         return m_cancelled;
313     }
314
315     void tryCancelled()
316     {
317         //DPL::Mutex::ScopedLock lock(&m_stateMutex);
318         if (m_cancelled) {
319             Throw(Commons::EventCancelledException);
320         }
321     }
322
323     bool getCancelAllowed() const
324     {
325         return m_cancelAllowed;
326     }
327
328     void setCancelAllowed(bool cancelAllowed)
329     {
330         m_cancelAllowed = cancelAllowed;
331     }
332
333     bool cancelRequest()
334     {
335         LogDebug("trying to cancel");
336         assert(
337             HANDLING_ASYNCHRONOUS == m_handlingType ||
338             HANDLING_ASYNCHRONOUS_MANUAL_ANSWER == m_handlingType);
339         {
340             DPL::Mutex::ScopedLock lock(&m_stateMutex);
341             if (m_cancelled) {
342                 return false;
343             }
344             switch (m_state) {
345             case STATE_INITIAL:
346                 assert(0);
347             case STATE_ANSWER_SEND:
348                 LogDebug("cancelling");
349                 m_cancelled = true;
350                 delete m_cancelStatusFlag;
351                 m_cancelStatusFlag = NULL;
352                 return m_cancelAllowed;
353             case STATE_ANSWER_RECEIVED:
354             case STATE_ENDED:
355                 return false;
356             default:
357                 break;
358             }
359             LogDebug("cancelling");
360             m_cancelled = true;
361         }
362         LogDebug("waiting for cancel flag");
363         DPL::WaitForSingleHandle(getCancelStatusFlag().GetHandle());
364         delete m_cancelStatusFlag;
365         m_cancelStatusFlag = NULL;
366         return m_cancelAllowed;
367     }
368 };
369 }
370 } // WrtDeviceApisCommon
371
372 #endif /* WRTDEVICEAPIS_COMMONS_IEVENT_H_ */