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 {
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 LogDebug("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 LogDebug("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)
112 LogDebug(__FUNCTION__);
114 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
115 assert(TemplateEvent::STATE_INITIAL == event->m_state);
116 event->m_state = TemplateEvent::STATE_REQUEST_SEND;
118 LogDebug("state changed to STATE_REQUEST_SEND. Now posting");
120 if (TemplateEvent::HANDLING_SYNCHRONOUS == event->getHandlingType() &&
121 !event->m_synchronousEventFlag)
123 event->m_synchronousEventFlag = new DPL::WaitableEvent();
126 if (0.0 == delaySeconds) {
127 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >
131 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >
133 PostTimedEvent(event, delaySeconds);
135 LogDebug("Event posted.");
136 switch (event->getHandlingType()) {
137 case TemplateEvent::HANDLING_NOT_SET:
140 case TemplateEvent::HANDLING_SYNCHRONOUS:
141 LogDebug("It's synchronous call - waiting for answer...");
142 event->waitForAnswer();
143 LogDebug("...answer received");
148 void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
150 LogDebug(__FUNCTION__);
152 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
153 if (event->m_cancelled) {
154 event->handleCancel();
155 event->m_cancelAllowed = true;
156 event->signalCancelStatusFlag();
157 event->signalFinishedFlag();
161 TemplateEvent::STATE_REQUEST_SEND == event->m_state &&
164 event->m_state = TemplateEvent::STATE_REQUEST_RECEIVED;
166 LogDebug("calling OnRequestReceived");
167 OnRequestReceived(event);
168 event->signalCancelStatusFlag();
169 //After Controller ends processing it should call it to signal that work
172 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
174 if (event->m_cancelled) {
175 //if cancel was not handled in OnRequestReceived when we should
176 //process as if it was not cancelled at all.
177 if (event->m_cancelAllowed) {
178 event->handleCancel();
179 event->signalFinishedFlag();
183 //when event is not in manual answer mode we will answer now
184 if (TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER !=
185 event->m_handlingType &&
186 TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER !=
187 event->m_handlingType)
189 event->m_state = TemplateEvent::STATE_ANSWER_SEND;
192 LogDebug("choosing the answer method");
193 switch (event->m_handlingType) {
194 case TemplateEvent::HANDLING_NOT_SET:
197 case TemplateEvent::HANDLING_SYNCHRONOUS:
199 signalEventByDispatcher(event);
201 case TemplateEvent::HANDLING_ASYNCHRONOUS:
202 ///TODO check - shouldn't it be in signalEventByDispatcher?
203 if (NULL != event->m_remoteController) {
204 event->m_remoteController->PostAnswer(event);
207 signalEventByDispatcher(event);
209 //when event is in manual answer mode we do nothing - the answer will be
210 // send explicit from the code
211 case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
212 case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
213 LogDebug("Manual answer is set so do nothing.");
218 virtual void ManualAnswer(const DPL::SharedPtr<TemplateEvent> &event)
220 LogDebug(__FUNCTION__);
222 event->m_handlingType ==
223 TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER ||
224 event->m_handlingType ==
225 TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER);
227 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
228 if (event->m_cancelled) {
229 //if cancel was not handled in OnRequestReceived when we should
230 //process as if it was not cancelled at all.
231 if (event->m_cancelAllowed) {
232 event->handleCancel();
233 event->signalCancelStatusFlag();
234 event->signalFinishedFlag();
238 event->m_state = TemplateEvent::STATE_ANSWER_SEND;
240 switch (event->m_handlingType) {
241 case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
243 signalEventByDispatcher(event);
245 case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
247 if (NULL != event->m_remoteController) {
248 event->m_remoteController->PostAnswer(event);
250 signalEventByDispatcher(event);
258 template<class TemplateEvent>
259 class EventAnswerReceiver : private EventReceiver<TemplateEvent>
262 EventAnswerReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
263 TemplateEvent>(threadType)
266 virtual void OnAnswerReceived(const DPL::SharedPtr<TemplateEvent> &event) =
269 //it should be hidden outside, but I can't do it! I can't! :|
270 void PostAnswer(const DPL::SharedPtr<TemplateEvent> &event)
272 LogDebug(__FUNCTION__);
273 event->signalCancelStatusFlag();
274 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
279 void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
281 LogDebug("EventAnswerReceiver: answer received");
282 //check if it can be processed and set the state
284 LogDebug("checking the state");
285 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
287 //in case someone changed it to synchronous call, we don't process
289 if (TemplateEvent::STATE_CHANGED_TO_SYNCHRONOUS ==
290 event->m_state || TemplateEvent::STATE_ENDED ==
294 "Handling probably changed to synchronous meanwhile. Will not process it..");
297 //we should get cancelled or answer_send state here
299 TemplateEvent::STATE_ANSWER_SEND == event->m_state &&
302 if (event->m_cancelled && event->m_cancelAllowed) {
303 event->handleCancel();
304 event->signalFinishedFlag();
307 event->m_state = TemplateEvent::STATE_ANSWER_RECEIVED;
309 LogDebug("calling OnAnswerReceived");
310 OnAnswerReceived(event);
312 LogDebug("changing the state");
314 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
315 assert(TemplateEvent::STATE_ANSWER_RECEIVED == event->m_state);
316 event->m_state = TemplateEvent::STATE_ENDED;
317 delete event->m_cancelStatusFlag;
318 event->m_cancelStatusFlag = NULL;
319 //if someone is waiting
320 event->signalFinishedFlag();
326 } // WrtDeviceApisCommon
328 #endif /* WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_ */