Change namespace
[platform/core/security/key-manager.git] / src / manager / main / service-thread.h
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Bumjin Im <bj.im@samsung.com>
5  *
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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
17  */
18 /*
19  * @file        service-thread.h
20  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
21  * @author      Zofia Abramowska (z.abramowska@samsung.com)
22  * @version     1.0
23  * @brief       Implementation of threads.
24  */
25
26 #ifndef _CENT_KEY_SERVICE_THREAD_
27 #define _CENT_KEY_SERVICE_THREAD_
28
29 #include <cassert>
30 #include <queue>
31 #include <mutex>
32 #include <thread>
33 #include <memory>
34 #include <condition_variable>
35
36 #include <cstdio>
37
38 #include <dpl/exception.h>
39
40 #include "generic-event.h"
41
42 #define DEFINE_THREAD_EVENT(eventType)                                \
43     void Event(const eventType &event) {                              \
44         CKM::ServiceThread<ParentClassName>::              \
45             Event(event,                                              \
46                   this,                                               \
47                   &ParentClassName::EventInternal##eventType);        \
48     }                                                                 \
49     void EventInternal##eventType(const eventType &event)
50
51 #define DECLARE_THREAD_EVENT(eventType, methodName)                   \
52     void Event(const eventType &event) {                              \
53         CKM::ServiceThread<ParentClassName>::              \
54             Event(event,                                              \
55                   this,                                               \
56                   &ParentClassName::methodName);                      \
57     }
58
59 namespace CKM {
60
61 template <class Service>
62 class ServiceThread {
63 public:
64     typedef Service ParentClassName;
65     enum class State {
66         NoThread,
67         Work,
68     };
69
70     ServiceThread()
71       : m_state(State::NoThread)
72       , m_quit(false)
73     {}
74
75     void Create() {
76         assert(m_state == State::NoThread);
77         m_thread = std::thread(ThreadLoopStatic, this);
78         m_state = State::Work;
79     }
80
81     void Join() {
82         assert(m_state != State::NoThread);
83         {
84             std::lock_guard<std::mutex> lock(m_eventQueueMutex);
85             m_quit = true;
86             m_waitCondition.notify_one();
87         }
88         m_thread.join();
89         m_state = State::NoThread;
90     }
91
92     virtual ~ServiceThread()
93     {
94         if (m_state != State::NoThread)
95             Join();
96         while (!m_eventQueue.empty()){
97             auto front = m_eventQueue.front();
98             delete front.eventPtr;
99             m_eventQueue.pop();
100         }
101     }
102
103     template <class T>
104     void Event(const T &event,
105                Service *servicePtr,
106                void (Service::*serviceFunction)(const T &))
107     {
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);
114         {
115             std::lock_guard<std::mutex> lock(m_eventQueueMutex);
116             m_eventQueue.push(description);
117         }
118         m_waitCondition.notify_one();
119     }
120
121 protected:
122
123     struct EventDescription {
124         void (Service::*serviceFunctionPtr)(void *);
125         Service *servicePtr;
126         void (ServiceThread::*eventFunctionPtr)(const EventDescription &event);
127         GenericEvent* eventPtr;
128     };
129
130     template <class T>
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);
135     }
136
137     static void ThreadLoopStatic(ServiceThread *ptr) {
138         ptr->ThreadLoop();
139     }
140
141     void ThreadLoop(){
142         for (;;) {
143             EventDescription description = {NULL, NULL, NULL, NULL};
144             {
145                 std::unique_lock<std::mutex> ulock(m_eventQueueMutex);
146                 if (m_quit)
147                     return;
148                 if (!m_eventQueue.empty()) {
149                     description = m_eventQueue.front();
150                     m_eventQueue.pop();
151                 } else {
152                     m_waitCondition.wait(ulock);
153                 }
154             }
155
156             if (description.eventPtr != NULL) {
157                 UNHANDLED_EXCEPTION_HANDLER_BEGIN
158                 {
159                     (this->*description.eventFunctionPtr)(description);
160                     delete description.eventPtr;
161                 }
162                 UNHANDLED_EXCEPTION_HANDLER_END
163             }
164         }
165     }
166
167     std::thread m_thread;
168     std::mutex m_eventQueueMutex;
169     std::queue<EventDescription> m_eventQueue;
170     std::condition_variable m_waitCondition;
171
172     State m_state;
173     bool m_quit;
174 };
175
176 } // namespace CKM
177
178 #endif // _CENT_KEY_SERVICE_THREAD_