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_
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>
36 namespace WrtDeviceApis {
38 template<class TemplateEvent>
39 class SignalEventCall : public DPL::Event::AbstractEventCall
41 DPL::SharedPtr<TemplateEvent> m_event;
45 SignalEventCall(const DPL::SharedPtr<TemplateEvent> &event) : m_event(event)
49 _D("signaling in SignalEventCall");
50 m_event->signalSynchronousEventFlag();
54 template<class TemplateEvent>
56 protected DPL::Event::Controller<
57 typename DPL::TypeListDecl<DPL::SharedPtr<TemplateEvent> >::Type>
59 DPL::Event::ThreadEventDispatcher m_threadDispatcher;
63 EventReceiver(ThreadEnum::Enumeration threadType)
66 ThreadPool::getInstance().getThreadRef(threadType);
67 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
69 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
70 SwitchToThread(thread);
73 void signalEventByDispatcher(const DPL::SharedPtr<TemplateEvent> &event)
77 DPL::Event::AbstractEventDispatcher *dispatcher =
78 ThreadPool::getInstance().getDispatcher(m_threadDispatcher);
79 dispatcher->AddEventCall(new SignalEventCall<TemplateEvent>(event));
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();
90 virtual ~EventReceiver()
92 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
97 template<class TemplateEvent>
98 class EventRequestReceiver : private EventReceiver<TemplateEvent>
101 EventRequestReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
102 TemplateEvent>(threadType)
104 virtual void OnRequestReceived(const DPL::SharedPtr<TemplateEvent> &)
105 { LogError("Pure virtual function call"); } //TODO: temporary code: DPL::SharedPtr -> std::shared_ptr
107 virtual void OnRequestReceived(const std::shared_ptr<TemplateEvent> &)
108 { LogError("Pure virtual function call"); }
112 * @argument delaySeconds - event will be received not sooner than after
115 void PostRequest(const DPL::SharedPtr<TemplateEvent> &event,
116 double delaySeconds = 0.0)
120 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
121 assert(TemplateEvent::STATE_INITIAL == event->m_state);
122 event->m_state = TemplateEvent::STATE_REQUEST_SEND;
125 if (TemplateEvent::HANDLING_SYNCHRONOUS == event->getHandlingType() &&
126 !event->m_synchronousEventFlag)
128 event->m_synchronousEventFlag = new DPL::WaitableEvent();
131 if (0.0 == delaySeconds) {
132 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >
136 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >
138 PostTimedEvent(event, delaySeconds);
141 switch (event->getHandlingType()) {
142 case TemplateEvent::HANDLING_NOT_SET:
145 case TemplateEvent::HANDLING_SYNCHRONOUS:
146 event->waitForAnswer();
151 void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
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();
164 TemplateEvent::STATE_REQUEST_SEND == event->m_state &&
167 event->m_state = TemplateEvent::STATE_REQUEST_RECEIVED;
170 OnRequestReceived(event);
171 event->signalCancelStatusFlag();
172 //After Controller ends processing it should call it to signal that work
175 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
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();
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)
192 event->m_state = TemplateEvent::STATE_ANSWER_SEND;
196 switch (event->m_handlingType) {
197 case TemplateEvent::HANDLING_NOT_SET:
200 case TemplateEvent::HANDLING_SYNCHRONOUS:
202 this->signalEventByDispatcher(event);
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);
210 this->signalEventByDispatcher(event);
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:
220 virtual void ManualAnswer(const DPL::SharedPtr<TemplateEvent> &event)
224 event->m_handlingType ==
225 TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER ||
226 event->m_handlingType ==
227 TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER);
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();
240 event->m_state = TemplateEvent::STATE_ANSWER_SEND;
242 switch (event->m_handlingType) {
243 case TemplateEvent::HANDLING_SYNCHRONOUS_MANUAL_ANSWER:
245 this->signalEventByDispatcher(event);
247 case TemplateEvent::HANDLING_ASYNCHRONOUS_MANUAL_ANSWER:
249 if (NULL != event->m_remoteController) {
250 event->m_remoteController->PostAnswer(event);
252 this->signalEventByDispatcher(event);
260 template<class TemplateEvent>
261 class EventAnswerReceiver : private EventReceiver<TemplateEvent>
264 EventAnswerReceiver(ThreadEnum::Enumeration threadType) : EventReceiver<
265 TemplateEvent>(threadType)
268 virtual void OnAnswerReceived(const DPL::SharedPtr<TemplateEvent> &)
269 { LogError("Pure virtual function call"); } //TODO: temporary code: DPL::SharedPtr -> std::shared_ptr
271 virtual void OnAnswerReceived(const std::shared_ptr<TemplateEvent> &)
272 { LogError("Pure virtual function call"); }
274 //it should be hidden outside, but I can't do it! I can't! :|
275 void PostAnswer(const DPL::SharedPtr<TemplateEvent> &event)
277 LogDebug(__FUNCTION__);
278 event->signalCancelStatusFlag();
279 DPL::Event::ControllerEventHandler<DPL::SharedPtr<TemplateEvent> >::
284 void OnEventReceived(const DPL::SharedPtr<TemplateEvent> &event)
286 _D("EventAnswerReceiver: answer received");
287 //check if it can be processed and set the state
289 DPL::Mutex::ScopedLock lock(&event->m_stateMutex);
291 //in case someone changed it to synchronous call, we don't process
293 if (TemplateEvent::STATE_CHANGED_TO_SYNCHRONOUS ==
294 event->m_state || TemplateEvent::STATE_ENDED ==
299 //we should get cancelled or answer_send state here
301 TemplateEvent::STATE_ANSWER_SEND == event->m_state &&
304 if (event->m_cancelled && event->m_cancelAllowed) {
305 event->handleCancel();
306 event->signalFinishedFlag();
309 event->m_state = TemplateEvent::STATE_ANSWER_RECEIVED;
312 OnAnswerReceived(event);
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();
326 } // WrtDeviceApisCommon
328 #endif /* WRTDEVICEAPIS_COMMONS_EVENT_RECEIVER_H_ */