tizen beta release
[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
35 class IEventPrivateData
36 {
37   public:
38     virtual ~IEventPrivateData()
39     {
40     }
41 };
42
43
44 class IEventController
45 {
46     DPL::SharedPtr<IEventPrivateData> m_privateData;
47   public:
48     virtual void waitTillProcessed() = 0;
49     virtual void waitForAnswer() = 0;
50     virtual bool cancelRequest()
51     {
52         return false;
53     }
54     virtual bool changeCallToSynchronous() = 0;
55     virtual ~IEventController()
56     {
57     }
58
59     void setPrivateData(
60             const DPL::SharedPtr<IEventPrivateData> &privateData)
61     {
62         m_privateData = privateData;
63     }
64     const DPL::SharedPtr<IEventPrivateData>& getPrivateData()
65     {
66         return m_privateData;
67     }
68 };
69 typedef DPL::SharedPtr<IEventController> IEventControllerPtr;
70
71
72 // CRTP pattern
73 template<class Super>
74 class IEvent : /*private DPL::WaitableEvent, */ public IEventController
75 {
76   public:
77     friend class EventRequestReceiver<Super>;
78     friend class EventAnswerReceiver<Super>;
79     friend class SignalEventCall<Super>;
80
81     enum HandlingType
82     {
83         HANDLING_NOT_SET = -1,
84         HANDLING_SYNCHRONOUS = 0,
85         HANDLING_ASYNCHRONOUS = 1,
86         HANDLING_SYNCHRONOUS_MANUAL_ANSWER = 2,
87         HANDLING_ASYNCHRONOUS_MANUAL_ANSWER = 3
88     };
89
90     enum State
91     {
92         STATE_INITIAL,
93         STATE_REQUEST_SEND,
94         STATE_REQUEST_RECEIVED,
95         STATE_ANSWER_SEND,
96         STATE_ANSWER_RECEIVED,
97         STATE_ENDED,
98         STATE_CHANGED_TO_SYNCHRONOUS
99     };
100
101   private:
102     void handleCancel()
103     {
104         clearOnCancel();
105         m_state = STATE_ENDED;
106         m_exceptionCode = Commons::ExceptionCodes::EventCancelledException;
107         //if someone is waiting
108         signalSynchronousEventFlag();
109     }
110   protected:
111     DPL::Mutex m_stateMutex;
112     State m_state;
113     HandlingType m_handlingType;
114     EventAnswerReceiver< Super > *m_remoteController;
115     Commons::ExceptionCodes::Enumeration m_exceptionCode;
116     DPL::WaitableEvent *m_synchronousEventFlag;
117     DPL::WaitableEvent *m_finishedFlag;
118     DPL::WaitableEvent *m_cancelStatusFlag;
119     bool m_cancelled;
120     bool m_cancelAllowed;
121
122     IEvent() :
123         m_state(STATE_INITIAL),
124         m_handlingType(HANDLING_NOT_SET),
125         m_remoteController(NULL),
126         m_exceptionCode(Commons::ExceptionCodes::None),
127         m_synchronousEventFlag(NULL),
128         m_finishedFlag(NULL),
129         m_cancelStatusFlag(NULL),
130         m_cancelled(false),
131         m_cancelAllowed(false)
132     {
133     }
134
135     virtual void waitForAnswer()
136     {
137         assert(HANDLING_SYNCHRONOUS == m_handlingType);
138         DPL::WaitForSingleHandle(m_synchronousEventFlag->GetHandle());
139         {
140             DPL::Mutex::ScopedLock lock(&m_stateMutex);
141             m_state = STATE_ENDED;
142         }
143         signalFinishedFlag();
144         LogDebug("deleting m_processEvent");
145         delete m_synchronousEventFlag;
146         m_synchronousEventFlag = NULL;
147     }
148
149     void signalFinishedFlag()
150     {
151         if (m_finishedFlag) {
152             m_finishedFlag->Signal();
153         }
154     }
155
156     DPL::WaitableEvent &getFinishedFlag()
157     {
158         if (!m_finishedFlag) {
159             m_finishedFlag = new DPL::WaitableEvent();
160         }
161         return *m_finishedFlag;
162     }
163
164     void signalCancelStatusFlag()
165     {
166         LogDebug("signaling cancel");
167         getCancelStatusFlag().Signal();
168     }
169
170     DPL::WaitableEvent &getCancelStatusFlag()
171     {
172         if (!m_cancelStatusFlag) {
173             m_cancelStatusFlag = new DPL::WaitableEvent();
174         }
175         return *m_cancelStatusFlag;
176     }
177
178     void signalSynchronousEventFlag()
179     {
180         if (m_synchronousEventFlag) {
181             m_synchronousEventFlag->Signal();
182         }
183     }
184
185   public:
186
187     /*
188      * Gets the answer receiver pointer.
189      */
190     EventAnswerReceiver< Super > * getAnswerReceiverRef() const
191     {
192         return m_remoteController;
193     }
194
195     virtual ~IEvent()
196     {
197         delete m_cancelStatusFlag;
198         delete m_finishedFlag;
199         delete m_synchronousEventFlag;
200     }
201
202     virtual bool changeCallToSynchronous()
203     {
204         return setForSynchronousCall();
205     }
206
207     virtual void waitTillProcessed()
208     {
209         DPL::WaitForSingleHandle(getFinishedFlag().GetHandle());
210         delete m_finishedFlag;
211         m_finishedFlag = NULL;
212     }
213
214     virtual void clearOnCancel()
215     {
216     }
217
218     Commons::ExceptionCodes::Enumeration getExceptionCode() const
219     {
220         return m_exceptionCode;
221     }
222     void setExceptionCode(Commons::ExceptionCodes::Enumeration exceptionCode)
223     {
224         m_exceptionCode = exceptionCode;
225     }
226
227     short getHandlingType() const
228     {
229         return m_handlingType;
230     }
231
232     virtual bool setForSynchronousCall()
233     {
234         DPL::Mutex::ScopedLock lock(&m_stateMutex);
235         if (m_cancelled) {
236             return false;
237         }
238         switch (m_state) {
239         case STATE_ANSWER_SEND:
240             m_state = STATE_CHANGED_TO_SYNCHRONOUS;
241             break;
242         case STATE_ANSWER_RECEIVED:
243         case STATE_ENDED:
244             return false;
245         default:
246             break;
247         }
248         m_handlingType = HANDLING_SYNCHRONOUS;
249         return true;
250     }
251
252     virtual bool setForAsynchronousCall(
253             EventAnswerReceiver< Super > *remoteController)
254     {
255         DPL::Mutex::ScopedLock lock(&m_stateMutex);
256         if (m_cancelled) {
257             return false;
258         }
259         switch (m_state) {
260         case STATE_ANSWER_SEND:
261         case STATE_ANSWER_RECEIVED:
262         case STATE_ENDED:
263             return false;
264         default:
265             break;
266         }
267         m_handlingType = HANDLING_ASYNCHRONOUS;
268         m_remoteController = remoteController;
269         return true;
270     }
271
272     /*
273      * Normally, after invoking OnRequestReceived in RequestReceiver, the answer is being send automatically (after flow leaves OnRequestReceived).
274      * After calling this function, the answer is not being send automatically, 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 }
371 } // WrtDeviceApisCommon
372
373 #endif /* WRTDEVICEAPIS_COMMONS_IEVENT_H_ */