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