2 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Bumjin Im <bj.im@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
19 * @file service-thread.h
20 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
21 * @author Zofia Abramowska (z.abramowska@samsung.com)
23 * @brief Implementation of threads.
26 #ifndef _CENT_KEY_SERVICE_THREAD_
27 #define _CENT_KEY_SERVICE_THREAD_
34 #include <condition_variable>
38 #include <dpl/exception.h>
40 #include "generic-event.h"
42 #define DEFINE_THREAD_EVENT(eventType) \
43 void Event(const eventType &event) { \
44 CKM::ServiceThread<ParentClassName>:: \
47 &ParentClassName::EventInternal##eventType); \
49 void EventInternal##eventType(const eventType &event)
51 #define DECLARE_THREAD_EVENT(eventType, methodName) \
52 void Event(const eventType &event) { \
53 CKM::ServiceThread<ParentClassName>:: \
56 &ParentClassName::methodName); \
61 template <class Service>
64 typedef Service ParentClassName;
71 : m_state(State::NoThread)
76 assert(m_state == State::NoThread);
77 m_thread = std::thread(ThreadLoopStatic, this);
78 m_state = State::Work;
82 assert(m_state != State::NoThread);
84 std::lock_guard<std::mutex> lock(m_eventQueueMutex);
86 m_waitCondition.notify_one();
89 m_state = State::NoThread;
92 virtual ~ServiceThread()
94 if (m_state != State::NoThread)
96 while (!m_eventQueue.empty()){
97 auto front = m_eventQueue.front();
98 delete front.eventPtr;
104 void Event(const T &event,
106 void (Service::*serviceFunction)(const T &))
108 EventDescription description;
109 description.serviceFunctionPtr =
110 reinterpret_cast<void (Service::*)(void*)>(serviceFunction);
111 description.servicePtr = servicePtr;
112 description.eventFunctionPtr = &ServiceThread::EventCall<T>;
113 description.eventPtr = new T(event);
115 std::lock_guard<std::mutex> lock(m_eventQueueMutex);
116 m_eventQueue.push(description);
118 m_waitCondition.notify_one();
123 struct EventDescription {
124 void (Service::*serviceFunctionPtr)(void *);
126 void (ServiceThread::*eventFunctionPtr)(const EventDescription &event);
127 GenericEvent* eventPtr;
131 void EventCall(const EventDescription &desc) {
132 auto fun = reinterpret_cast<void (Service::*)(const T&)>(desc.serviceFunctionPtr);
133 const T& eventLocale = *(static_cast<T*>(desc.eventPtr));
134 (desc.servicePtr->*fun)(eventLocale);
137 static void ThreadLoopStatic(ServiceThread *ptr) {
143 EventDescription description = {NULL, NULL, NULL, NULL};
145 std::unique_lock<std::mutex> ulock(m_eventQueueMutex);
148 if (!m_eventQueue.empty()) {
149 description = m_eventQueue.front();
152 m_waitCondition.wait(ulock);
156 if (description.eventPtr != NULL) {
157 UNHANDLED_EXCEPTION_HANDLER_BEGIN
159 (this->*description.eventFunctionPtr)(description);
160 delete description.eventPtr;
162 UNHANDLED_EXCEPTION_HANDLER_END
167 std::thread m_thread;
168 std::mutex m_eventQueueMutex;
169 std::queue<EventDescription> m_eventQueue;
170 std::condition_variable m_waitCondition;
178 #endif // _CENT_KEY_SERVICE_THREAD_