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/log.h>
31 #include <Commons/ThreadPool.h>
33 namespace WrtDeviceApis {
36 template<class TemplateEvent>
37 class SignalEventCall : public DPL::Event::AbstractEventCall
39 DPL::SharedPtr<TemplateEvent> m_event;
42 SignalEventCall(const DPL::SharedPtr<TemplateEvent> &event) : m_event(event)
47 LogDebug("signaling in SignalEventCall");
48 m_event->signalSynchronousEventFlag();
53 template<class TemplateEvent>
55 protected DPL::Event::Controller<
56 typename DPL::TypeListDecl<DPL::SharedPtr<TemplateEvent> >::Type>
58 DPL::Event::ThreadEventDispatcher m_threadDispatcher;
61 EventReceiver(ThreadEnum::Enumeration threadType)
64 ThreadPool::getInstance().getThreadRef(threadType);
65 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
67 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
68 SwitchToThread(thread);
71 void signalEventByDispatcher(const DPL::SharedPtr<TemplateEvent> &event)
75 DPL::Event::AbstractEventDispatcher *dispatcher =
76 ThreadPool::getInstance().getDispatcher(m_threadDispatcher);
77 dispatcher->AddEventCall(new SignalEventCall<TemplateEvent>(event));
79 Catch(DPL::Thread::Exception::UnmanagedThread) {
80 // if called on unmanaged thread,
81 // call signalSynchronousEventFlag() directly
82 LogDebug("signalSynchronousEventFlag() is called"
83 "by unmanaged thread");
84 event->signalSynchronousEventFlag();
88 virtual ~EventReceiver()
90 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
96 template<class TemplateEvent>
97 class EventRequestReceiver : private EventReceiver<TemplateEvent>
100 EventRequestReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
101 TemplateEvent>(threadType)
104 virtual void OnRequestReceived(const DPL::SharedPtr<TemplateEvent> &event)
109 * @argument delaySeconds - event will be received not sooner than after delay (in seconds)
111 void PostRequest(const DPL::SharedPtr<TemplateEvent> &event,
112 double delaySeconds = 0.0)
114 LogDebug(__FUNCTION__);
116 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
117 assert(TemplateEvent::STATE_INITIAL == event->m_state);
118 event->m_state = TemplateEvent::STATE_REQUEST_SEND;
120 LogDebug("state changed to STATE_REQUEST_SEND. Now posting");
122 if (TemplateEvent::HANDLING_SYNCHRONOUS == event->getHandlingType() &&
123 !event->m_synchronousEventFlag) {
124 event->m_synchronousEventFlag = new DPL::WaitableEvent();
127 if (0.0 == delaySeconds) {
128 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
131 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
132 PostTimedEvent(event, delaySeconds);
134 LogDebug("Event posted.");
135 switch (event->getHandlingType()) {
136 case TemplateEvent::HANDLING_NOT_SET:
139 case TemplateEvent::HANDLING_SYNCHRONOUS:
140 LogDebug("It's synchronous call - waiting for answer...");
141 event->waitForAnswer();
142 LogDebug("...answer received");
147 void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
149 LogDebug(__FUNCTION__);
151 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
152 if (event->m_cancelled) {
153 event->handleCancel();
154 event->m_cancelAllowed = true;
155 event->signalCancelStatusFlag();
156 event->signalFinishedFlag();
160 TemplateEvent::STATE_REQUEST_SEND == event->m_state &&
163 event->m_state = TemplateEvent::STATE_REQUEST_RECEIVED;
165 LogDebug("calling OnRequestReceived");
166 OnRequestReceived(event);
167 event->signalCancelStatusFlag();
168 //After Controller ends processing it should call it to signal that work is done
170 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
172 if (event->m_cancelled) {
173 //if cancel was not handled in OnRequestReceived when we should
174 //process as if it was not cancelled at all.
175 if (event->m_cancelAllowed) {
176 event->handleCancel();
177 event->signalFinishedFlag();
181 //when event is not in manual answer mode we will answer now
182 if (TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER !=
183 event->m_handlingType &&
184 TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER !=
185 event->m_handlingType) {
186 event->m_state = TemplateEvent::STATE_ANSWER_SEND;
189 LogDebug("choosing the answer method");
190 switch (event->m_handlingType) {
191 case TemplateEvent::HANDLING_NOT_SET:
194 case TemplateEvent::HANDLING_SYNCHRONOUS:
196 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 signalEventByDispatcher(event);
206 //when event is in manual answer mode we do nothing - the answer will be send explicit from the code
207 case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
208 case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
209 LogDebug("Manual answer is set so do nothing.");
214 virtual void ManualAnswer(const DPL::SharedPtr<TemplateEvent> &event)
216 LogDebug(__FUNCTION__);
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 signalEventByDispatcher(event);
241 case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
243 if (NULL != event->m_remoteController) {
244 event->m_remoteController->PostAnswer(event);
246 signalEventByDispatcher(event);
255 template<class TemplateEvent>
256 class EventAnswerReceiver : private EventReceiver<TemplateEvent>
259 EventAnswerReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
260 TemplateEvent>(threadType)
264 virtual void OnAnswerReceived(const DPL::SharedPtr<TemplateEvent> &event) =
267 //it should be hidden outside, but I can't do it! I can't! :|
268 void PostAnswer(const DPL::SharedPtr<TemplateEvent> &event)
270 LogDebug(__FUNCTION__);
271 event->signalCancelStatusFlag();
272 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::PostEvent(
276 void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
278 LogDebug("EventAnswerReceiver: answer received");
279 //check if it can be processed and set the state
281 LogDebug("checking the state");
282 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
284 //in case someone changed it to synchronous call, we don't process it
285 if (TemplateEvent::STATE_CHANGED_TO_SYNCHRONOUS ==
286 event->m_state || TemplateEvent::STATE_ENDED ==
289 "Handling probably changed to synchronous meanwhile. Will not process it..");
292 //we should get cancelled or answer_send state here
294 TemplateEvent::STATE_ANSWER_SEND == event->m_state &&
297 if (event->m_cancelled && event->m_cancelAllowed) {
298 event->handleCancel();
299 event->signalFinishedFlag();
302 event->m_state = TemplateEvent::STATE_ANSWER_RECEIVED;
304 LogDebug("calling OnAnswerReceived");
305 OnAnswerReceived(event);
307 LogDebug("changing the state");
309 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
310 assert(TemplateEvent::STATE_ANSWER_RECEIVED == event->m_state);
311 event->m_state = TemplateEvent::STATE_ENDED;
312 delete event->m_cancelStatusFlag;
313 event->m_cancelStatusFlag = NULL;
314 //if someone is waiting
315 event->signalFinishedFlag();
322 } // WrtDeviceApisCommon
324 #endif /* WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_ */