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