2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @author Karol Majewski (k.majewski@samsung.com)
21 #ifndef WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_
22 #define WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_
25 #include <dpl/event/thread_event_dispatcher.h>
26 #include <dpl/shared_ptr.h>
27 #include <dpl/event/controller.h>
28 #include <dpl/type_list.h>
29 #include <dpl/event/abstract_event_call.h>
30 #include <dpl/log/secure_log.h>
31 #include <Commons/ThreadPool.h>
33 namespace WrtDeviceApis {
35 template<class TemplateEvent>
36 class SignalEventCall : public DPL::Event::AbstractEventCall
38 DPL::SharedPtr<TemplateEvent> m_event;
42 SignalEventCall(const DPL::SharedPtr<TemplateEvent> &event) : m_event(event)
46 _D("signaling in SignalEventCall");
47 m_event->signalSynchronousEventFlag();
51 template<class TemplateEvent>
53 protected DPL::Event::Controller<
54 typename DPL::TypeListDecl<DPL::SharedPtr<TemplateEvent> >::Type>
56 DPL::Event::ThreadEventDispatcher m_threadDispatcher;
60 EventReceiver(ThreadEnum::Enumeration threadType)
63 ThreadPool::getInstance().getThreadRef(threadType);
64 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
66 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
67 SwitchToThread(thread);
70 void signalEventByDispatcher(const DPL::SharedPtr<TemplateEvent> &event)
74 DPL::Event::AbstractEventDispatcher *dispatcher =
75 ThreadPool::getInstance().getDispatcher(m_threadDispatcher);
76 dispatcher->AddEventCall(new SignalEventCall<TemplateEvent>(event));
78 Catch(DPL::Thread::Exception::UnmanagedThread) {
79 // if called on unmanaged thread,
80 // call signalSynchronousEventFlag() directly
81 _E("signalSynchronousEventFlag() is called"
82 "by unmanaged thread");
83 event->signalSynchronousEventFlag();
87 virtual ~EventReceiver()
89 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
94 template<class TemplateEvent>
95 class EventRequestReceiver : private EventReceiver<TemplateEvent>
98 EventRequestReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
99 TemplateEvent>(threadType)
101 virtual void OnRequestReceived(const DPL::SharedPtr<TemplateEvent> &event)
106 * @argument delaySeconds - event will be received not sooner than after
109 void PostRequest(const DPL::SharedPtr<TemplateEvent> &event,
110 double delaySeconds = 0.0)
114 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
115 assert(TemplateEvent::STATE_INITIAL == event->m_state);
116 event->m_state = TemplateEvent::STATE_REQUEST_SEND;
119 if (TemplateEvent::HANDLING_SYNCHRONOUS == event->getHandlingType() &&
120 !event->m_synchronousEventFlag)
122 event->m_synchronousEventFlag = new DPL::WaitableEvent();
125 if (0.0 == delaySeconds) {
126 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >
130 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >
132 PostTimedEvent(event, delaySeconds);
135 switch (event->getHandlingType()) {
136 case TemplateEvent::HANDLING_NOT_SET:
139 case TemplateEvent::HANDLING_SYNCHRONOUS:
140 event->waitForAnswer();
145 void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
149 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
150 if (event->m_cancelled) {
151 event->handleCancel();
152 event->m_cancelAllowed = true;
153 event->signalCancelStatusFlag();
154 event->signalFinishedFlag();
158 TemplateEvent::STATE_REQUEST_SEND == event->m_state &&
161 event->m_state = TemplateEvent::STATE_REQUEST_RECEIVED;
164 OnRequestReceived(event);
165 event->signalCancelStatusFlag();
166 //After Controller ends processing it should call it to signal that work
169 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
171 if (event->m_cancelled) {
172 //if cancel was not handled in OnRequestReceived when we should
173 //process as if it was not cancelled at all.
174 if (event->m_cancelAllowed) {
175 event->handleCancel();
176 event->signalFinishedFlag();
180 //when event is not in manual answer mode we will answer now
181 if (TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER !=
182 event->m_handlingType &&
183 TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER !=
184 event->m_handlingType)
186 event->m_state = TemplateEvent::STATE_ANSWER_SEND;
190 switch (event->m_handlingType) {
191 case TemplateEvent::HANDLING_NOT_SET:
194 case TemplateEvent::HANDLING_SYNCHRONOUS:
196 this->signalEventByDispatcher(event);
198 case TemplateEvent::HANDLING_ASYNCHRONOUS:
199 ///TODO check - shouldn't it be in signalEventByDispatcher?
200 if (NULL != event->m_remoteController) {
201 event->m_remoteController->PostAnswer(event);
204 this->signalEventByDispatcher(event);
206 //when event is in manual answer mode we do nothing - the answer will be
207 // send explicit from the code
208 case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
209 case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
214 virtual void ManualAnswer(const DPL::SharedPtr<TemplateEvent> &event)
218 event->m_handlingType ==
219 TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER ||
220 event->m_handlingType ==
221 TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER);
223 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
224 if (event->m_cancelled) {
225 //if cancel was not handled in OnRequestReceived when we should
226 //process as if it was not cancelled at all.
227 if (event->m_cancelAllowed) {
228 event->handleCancel();
229 event->signalCancelStatusFlag();
230 event->signalFinishedFlag();
234 event->m_state = TemplateEvent::STATE_ANSWER_SEND;
236 switch (event->m_handlingType) {
237 case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
239 this->signalEventByDispatcher(event);
241 case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
243 if (NULL != event->m_remoteController) {
244 event->m_remoteController->PostAnswer(event);
246 this->signalEventByDispatcher(event);
254 template<class TemplateEvent>
255 class EventAnswerReceiver : private EventReceiver<TemplateEvent>
258 EventAnswerReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
259 TemplateEvent>(threadType)
262 virtual void OnAnswerReceived(const DPL::SharedPtr<TemplateEvent> &event) =
265 //it should be hidden outside, but I can't do it! I can't! :|
266 void PostAnswer(const DPL::SharedPtr<TemplateEvent> &event)
268 LogDebug(__FUNCTION__);
269 event->signalCancelStatusFlag();
270 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
275 void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
277 _D("EventAnswerReceiver: answer received");
278 //check if it can be processed and set the state
280 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
282 //in case someone changed it to synchronous call, we don't process
284 if (TemplateEvent::STATE_CHANGED_TO_SYNCHRONOUS ==
285 event->m_state || TemplateEvent::STATE_ENDED ==
290 //we should get cancelled or answer_send state here
292 TemplateEvent::STATE_ANSWER_SEND == event->m_state &&
295 if (event->m_cancelled && event->m_cancelAllowed) {
296 event->handleCancel();
297 event->signalFinishedFlag();
300 event->m_state = TemplateEvent::STATE_ANSWER_RECEIVED;
303 OnAnswerReceived(event);
306 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
307 assert(TemplateEvent::STATE_ANSWER_RECEIVED == event->m_state);
308 event->m_state = TemplateEvent::STATE_ENDED;
309 delete event->m_cancelStatusFlag;
310 event->m_cancelStatusFlag = NULL;
311 //if someone is waiting
312 event->signalFinishedFlag();
317 } // WrtDeviceApisCommon
319 #endif /* WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_ */