Initialize Tizen 2.3
[framework/web/wrt-plugins-common.git] / src_wearable / Commons / EventReceiver.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 #ifndef WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_
22 #define WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_
23
24 #include <memory>
25 #include <assert.h>
26 #include <dpl/event/thread_event_dispatcher.h>
27 #include <dpl/shared_ptr.h>
28 #include <dpl/event/controller.h>
29 #include <dpl/type_list.h>
30 #include <dpl/event/abstract_event_call.h>
31 #include <dpl/log/secure_log.h>
32 #include <dpl/mutex.h>
33 #include <dpl/shared_ptr.h>
34 #include <Commons/ThreadPool.h>
35
36 namespace WrtDeviceApis {
37 namespace Commons {
38 template<class TemplateEvent>
39 class SignalEventCall : public DPL::Event::AbstractEventCall
40 {
41     DPL::SharedPtr<TemplateEvent> m_event;
42
43   public:
44
45     SignalEventCall(const DPL::SharedPtr<TemplateEvent> &event) : m_event(event)
46     {}
47     virtual void Call()
48     {
49         _D("signaling in SignalEventCall");
50         m_event->signalSynchronousEventFlag();
51     }
52 };
53
54 template<class TemplateEvent>
55 class EventReceiver :
56     protected DPL::Event::Controller<
57         typename DPL::TypeListDecl<DPL::SharedPtr<TemplateEvent> >::Type>
58 {
59     DPL::Event::ThreadEventDispatcher m_threadDispatcher;
60
61   protected:
62
63     EventReceiver(ThreadEnum::Enumeration threadType)
64     {
65         DPL::Thread *thread =
66             ThreadPool::getInstance().getThreadRef(threadType);
67         DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
68             Touch();
69         DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
70             SwitchToThread(thread);
71     }
72
73     void signalEventByDispatcher(const DPL::SharedPtr<TemplateEvent> &event)
74     {
75         _D("called");
76         Try {
77             DPL::Event::AbstractEventDispatcher *dispatcher =
78                 ThreadPool::getInstance().getDispatcher(m_threadDispatcher);
79             dispatcher->AddEventCall(new SignalEventCall<TemplateEvent>(event));
80         }
81         Catch(DPL::Thread::Exception::UnmanagedThread) {
82             // if called on unmanaged thread,
83             // call signalSynchronousEventFlag() directly
84             _E("signalSynchronousEventFlag() is called"
85                      "by unmanaged thread");
86             event->signalSynchronousEventFlag();
87         }
88     }
89
90     virtual ~EventReceiver()
91     {
92         DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
93             SwitchToThread(NULL);
94     }
95 };
96
97 template<class TemplateEvent>
98 class EventRequestReceiver : private EventReceiver<TemplateEvent>
99 {
100   public:
101     EventRequestReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
102             TemplateEvent>(threadType)
103     {}
104     virtual void OnRequestReceived(const DPL::SharedPtr<TemplateEvent> &)
105     { LogError("Pure virtual function call"); } //TODO: temporary code: DPL::SharedPtr -> std::shared_ptr
106
107     virtual void OnRequestReceived(const std::shared_ptr<TemplateEvent> &)
108     { LogError("Pure virtual function call"); }
109
110     /*
111      *
112      * @argument delaySeconds - event will be received not sooner than after
113      * delay (in seconds)
114      */
115     void PostRequest(const DPL::SharedPtr<TemplateEvent> &event,
116                      double delaySeconds = 0.0)
117     {
118         _D("called");
119         {
120             DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
121             assert(TemplateEvent::STATE_INITIAL == event->m_state);
122             event->m_state = TemplateEvent::STATE_REQUEST_SEND;
123         }
124
125         if (TemplateEvent::HANDLING_SYNCHRONOUS == event->getHandlingType() &&
126             !event->m_synchronousEventFlag)
127         {
128             event->m_synchronousEventFlag = new DPL::WaitableEvent();
129         }
130
131         if (0.0 == delaySeconds) {
132             DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >
133                 ::
134                 PostEvent(event);
135         } else {
136             DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >
137                 ::
138                 PostTimedEvent(event, delaySeconds);
139         }
140
141         switch (event->getHandlingType()) {
142         case TemplateEvent::HANDLING_NOT_SET:
143             assert(0);
144             break;
145         case TemplateEvent::HANDLING_SYNCHRONOUS:
146             event->waitForAnswer();
147             break;
148         }
149     }
150
151     void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
152     {
153         _D("called");
154         {
155             DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
156             if (event->m_cancelled) {
157                 event->handleCancel();
158                 event->m_cancelAllowed = true;
159                 event->signalCancelStatusFlag();
160                 event->signalFinishedFlag();
161                 return;
162             } else {
163                 assert(
164                     TemplateEvent::STATE_REQUEST_SEND == event->m_state &&
165                     "Wrong state!");
166             }
167             event->m_state = TemplateEvent::STATE_REQUEST_RECEIVED;
168         }
169
170         OnRequestReceived(event);
171         event->signalCancelStatusFlag();
172         //After Controller ends processing it should call it to signal that work
173         // is done
174         {
175             DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
176
177             if (event->m_cancelled) {
178                 //if cancel was not handled in OnRequestReceived when we should
179                 //process as if it was not cancelled at all.
180                 if (event->m_cancelAllowed) {
181                     event->handleCancel();
182                     event->signalFinishedFlag();
183                     return;
184                 }
185             }
186             //when event is not in manual answer mode we will answer now
187             if (TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER !=
188                 event->m_handlingType &&
189                 TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER !=
190                 event->m_handlingType)
191             {
192                 event->m_state = TemplateEvent::STATE_ANSWER_SEND;
193             }
194         }
195
196         switch (event->m_handlingType) {
197         case TemplateEvent::HANDLING_NOT_SET:
198             assert(0);
199             break;
200         case TemplateEvent::HANDLING_SYNCHRONOUS:
201             //event->Signal();
202             this->signalEventByDispatcher(event);
203             break;
204         case TemplateEvent::HANDLING_ASYNCHRONOUS:
205             ///TODO check - shouldn't it be in signalEventByDispatcher?
206             if (NULL != event->m_remoteController) {
207                 event->m_remoteController->PostAnswer(event);
208             }
209             //event->Signal();
210             this->signalEventByDispatcher(event);
211             break;
212         //when event is in manual answer mode we do nothing - the answer will be
213         // send explicit from the code
214         case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
215         case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
216             break;
217         }
218     }
219
220     virtual void ManualAnswer(const DPL::SharedPtr<TemplateEvent> &event)
221     {
222         _D("called");
223         assert(
224             event->m_handlingType ==
225             TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER ||
226             event->m_handlingType ==
227             TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER);
228         {
229             DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
230             if (event->m_cancelled) {
231                 //if cancel was not handled in OnRequestReceived when we should
232                 //process as if it was not cancelled at all.
233                 if (event->m_cancelAllowed) {
234                     event->handleCancel();
235                     event->signalCancelStatusFlag();
236                     event->signalFinishedFlag();
237                     return;
238                 }
239             }
240             event->m_state = TemplateEvent::STATE_ANSWER_SEND;
241         }
242         switch (event->m_handlingType) {
243         case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
244             //event->Signal();
245             this->signalEventByDispatcher(event);
246             break;
247         case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
248             //event->Signal();
249             if (NULL != event->m_remoteController) {
250                 event->m_remoteController->PostAnswer(event);
251             }
252             this->signalEventByDispatcher(event);
253             break;
254         default:
255             break;
256         }
257     }
258 };
259
260 template<class TemplateEvent>
261 class EventAnswerReceiver : private EventReceiver<TemplateEvent>
262 {
263   public:
264     EventAnswerReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
265             TemplateEvent>(threadType)
266     {}
267
268     virtual void OnAnswerReceived(const DPL::SharedPtr<TemplateEvent> &)
269     { LogError("Pure virtual function call"); } //TODO: temporary code: DPL::SharedPtr -> std::shared_ptr
270
271     virtual void OnAnswerReceived(const std::shared_ptr<TemplateEvent> &)
272     { LogError("Pure virtual function call"); }
273
274     //it should be hidden outside, but I can't do it! I can't! :|
275     void PostAnswer(const DPL::SharedPtr<TemplateEvent> &event)
276     {
277         LogDebug(__FUNCTION__);
278         event->signalCancelStatusFlag();
279         DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
280             PostEvent(
281             event);
282     }
283
284     void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
285     {
286         _D("EventAnswerReceiver: answer received");
287         //check if it can be processed and set the state
288         {
289             DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
290
291             //in case someone changed it to synchronous call, we don't process
292             // it
293             if (TemplateEvent::STATE_CHANGED_TO_SYNCHRONOUS ==
294                 event->m_state || TemplateEvent::STATE_ENDED ==
295                 event->m_state)
296             {
297                 return;
298             }
299             //we should get cancelled or answer_send state here
300             assert(
301                 TemplateEvent::STATE_ANSWER_SEND == event->m_state &&
302                 "Wrong state!");
303
304             if (event->m_cancelled && event->m_cancelAllowed) {
305                 event->handleCancel();
306                 event->signalFinishedFlag();
307                 return;
308             }
309             event->m_state = TemplateEvent::STATE_ANSWER_RECEIVED;
310         }
311
312         OnAnswerReceived(event);
313
314         {
315             DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
316             assert(TemplateEvent::STATE_ANSWER_RECEIVED == event->m_state);
317             event->m_state = TemplateEvent::STATE_ENDED;
318             delete event->m_cancelStatusFlag;
319             event->m_cancelStatusFlag = NULL;
320             //if someone is waiting
321             event->signalFinishedFlag();
322         }
323     }
324 };
325 }
326 } // WrtDeviceApisCommon
327
328 #endif /* WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_ */