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)
74 DPL::Event::AbstractEventDispatcher *dispatcher =
75 ThreadPool::getInstance().getDispatcher(m_threadDispatcher);
76 dispatcher->AddEventCall(new SignalEventCall<TemplateEvent>(event));
79 virtual ~EventReceiver()
81 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
87 template<class TemplateEvent>
88 class EventRequestReceiver : private EventReceiver<TemplateEvent>
91 EventRequestReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
92 TemplateEvent>(threadType)
95 virtual void OnRequestReceived(const DPL::SharedPtr<TemplateEvent> &event)
100 * @argument delaySeconds - event will be received not sooner than after delay (in seconds)
102 void PostRequest(const DPL::SharedPtr<TemplateEvent> &event,
103 double delaySeconds = 0.0)
105 LogDebug(__FUNCTION__);
107 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
108 assert(TemplateEvent::STATE_INITIAL == event->m_state);
109 event->m_state = TemplateEvent::STATE_REQUEST_SEND;
111 LogDebug("state changed to STATE_REQUEST_SEND. Now posting");
113 if (TemplateEvent::HANDLING_SYNCHRONOUS == event->getHandlingType() &&
114 !event->m_synchronousEventFlag) {
115 event->m_synchronousEventFlag = new DPL::WaitableEvent();
118 if (0.0 == delaySeconds) {
119 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
122 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
123 PostTimedEvent(event, delaySeconds);
125 LogDebug("Event posted.");
126 switch (event->getHandlingType()) {
127 case TemplateEvent::HANDLING_NOT_SET:
130 case TemplateEvent::HANDLING_SYNCHRONOUS:
131 LogDebug("It's synchronous call - waiting for answer...");
132 event->waitForAnswer();
133 LogDebug("...answer received");
138 void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
140 LogDebug(__FUNCTION__);
142 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
143 if (event->m_cancelled) {
144 event->handleCancel();
145 event->m_cancelAllowed = true;
146 event->signalCancelStatusFlag();
147 event->signalFinishedFlag();
151 TemplateEvent::STATE_REQUEST_SEND == event->m_state &&
154 event->m_state = TemplateEvent::STATE_REQUEST_RECEIVED;
156 LogDebug("calling OnRequestReceived");
157 OnRequestReceived(event);
158 event->signalCancelStatusFlag();
159 //After Controller ends processing it should call it to signal that work is done
161 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
163 if (event->m_cancelled) {
164 //if cancel was not handled in OnRequestReceived when we should
165 //process as if it was not cancelled at all.
166 if (event->m_cancelAllowed) {
167 event->handleCancel();
168 event->signalFinishedFlag();
172 //when event is not in manual answer mode we will answer now
173 if (TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER !=
174 event->m_handlingType &&
175 TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER !=
176 event->m_handlingType) {
177 event->m_state = TemplateEvent::STATE_ANSWER_SEND;
180 LogDebug("choosing the answer method");
181 switch (event->m_handlingType) {
182 case TemplateEvent::HANDLING_NOT_SET:
185 case TemplateEvent::HANDLING_SYNCHRONOUS:
187 signalEventByDispatcher(event);
189 case TemplateEvent::HANDLING_ASYNCHRONOUS:
190 ///TODO check - shouldn't it be in signalEventByDispatcher?
191 if (NULL != event->m_remoteController) {
192 event->m_remoteController->PostAnswer(event);
195 signalEventByDispatcher(event);
197 //when event is in manual answer mode we do nothing - the answer will be send explicit from the code
198 case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
199 case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
200 LogDebug("Manual answer is set so do nothing.");
205 virtual void ManualAnswer(const DPL::SharedPtr<TemplateEvent> &event)
207 LogDebug(__FUNCTION__);
209 event->m_handlingType ==
210 TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER ||
211 event->m_handlingType ==
212 TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER);
214 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
215 if (event->m_cancelled) {
216 //if cancel was not handled in OnRequestReceived when we should
217 //process as if it was not cancelled at all.
218 if (event->m_cancelAllowed) {
219 event->handleCancel();
220 event->signalCancelStatusFlag();
221 event->signalFinishedFlag();
225 event->m_state = TemplateEvent::STATE_ANSWER_SEND;
227 switch (event->m_handlingType) {
228 case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
230 signalEventByDispatcher(event);
232 case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
234 if (NULL != event->m_remoteController) {
235 event->m_remoteController->PostAnswer(event);
237 signalEventByDispatcher(event);
246 template<class TemplateEvent>
247 class EventAnswerReceiver : private EventReceiver<TemplateEvent>
250 EventAnswerReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
251 TemplateEvent>(threadType)
255 virtual void OnAnswerReceived(const DPL::SharedPtr<TemplateEvent> &event) =
258 //it should be hidden outside, but I can't do it! I can't! :|
259 void PostAnswer(const DPL::SharedPtr<TemplateEvent> &event)
261 LogDebug(__FUNCTION__);
262 event->signalCancelStatusFlag();
263 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::PostEvent(
267 void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
269 LogDebug("EventAnswerReceiver: answer received");
270 //check if it can be processed and set the state
272 LogDebug("checking the state");
273 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
275 //in case someone changed it to synchronous call, we don't process it
276 if (TemplateEvent::STATE_CHANGED_TO_SYNCHRONOUS ==
277 event->m_state || TemplateEvent::STATE_ENDED ==
280 "Handling probably changed to synchronous meanwhile. Will not process it..");
283 //we should get cancelled or answer_send state here
285 TemplateEvent::STATE_ANSWER_SEND == event->m_state &&
288 if (event->m_cancelled && event->m_cancelAllowed) {
289 event->handleCancel();
290 event->signalFinishedFlag();
293 event->m_state = TemplateEvent::STATE_ANSWER_RECEIVED;
295 LogDebug("calling OnAnswerReceived");
296 OnAnswerReceived(event);
298 LogDebug("changing the state");
300 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
301 assert(TemplateEvent::STATE_ANSWER_RECEIVED == event->m_state);
302 event->m_state = TemplateEvent::STATE_ENDED;
303 delete event->m_cancelStatusFlag;
304 event->m_cancelStatusFlag = NULL;
305 //if someone is waiting
306 event->signalFinishedFlag();
313 } // WrtDeviceApisCommon
315 #endif /* WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_ */