a1b9d0c9ac850351b3d8b2719a41909562f82e96
[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 <functional>
35 #include <condition_variable>
36
37 #include <crypto-init.h>
38
39 #include <cstdio>
40
41 #include <dpl/exception.h>
42
43 #include "generic-event.h"
44
45 namespace CKM {
46
47 class ServiceThread {
48 public:
49         typedef std::function<void(void)> EventDescription;
50         enum class State {
51                 NoThread,
52                 Work,
53         };
54
55         ServiceThread() : m_state(State::NoThread), m_quit(false) {}
56
57         void Create()
58         {
59                 assert(m_state == State::NoThread);
60                 m_thread = std::thread(ThreadLoopStatic, this);
61                 m_state = State::Work;
62         }
63
64         void Join()
65         {
66                 assert(m_state != State::NoThread);
67
68                 {
69                         std::lock_guard<std::mutex> lock(this->m_eventQueueMutex);
70                         m_quit = true;
71                         m_waitCondition.notify_one();
72                 }
73
74                 m_thread.join();
75                 m_state = State::NoThread;
76         }
77
78         virtual ~ServiceThread()
79         {
80                 assert((m_state == State::NoThread) &&
81                            "Thread was not stopped before ServiceThread destruction!");
82         }
83
84 protected:
85         /*
86          * This function is always called from ThreadService::ThreadEvent where fun
87          * is created as a temporary object and therefore will not be copied.
88          */
89         void CreateEvent(std::function<void(void)> fun)
90         {
91                 EventDescription description;
92                 description = std::move(fun);
93
94                 {
95                         std::lock_guard<std::mutex> lock(this->m_eventQueueMutex);
96                         m_eventQueue.push(description);
97                 }
98
99                 m_waitCondition.notify_one();
100         }
101
102         static void ThreadLoopStatic(ServiceThread *ptr)
103         {
104                 ptr->ThreadLoop();
105
106                 // cleanup openssl in every thread
107                 deinitOpenSslThread();
108         }
109
110         void ThreadLoop()
111         {
112                 while (true) {
113                         EventDescription description;
114
115                         {
116                                 std::unique_lock<std::mutex> ulock(m_eventQueueMutex);
117
118                                 if (m_quit)
119                                         return;
120
121                                 if (!m_eventQueue.empty()) {
122                                         description = m_eventQueue.front();
123                                         m_eventQueue.pop();
124                                 } else {
125                                         m_waitCondition.wait(ulock);
126                                 }
127                         }
128
129                         if (description) {
130                                 try {
131                                         description();
132                                 }
133
134                                 UNHANDLED_EXCEPTION_HANDLER_END
135                         }
136                 }
137         }
138
139         std::thread m_thread;
140         std::mutex m_eventQueueMutex;
141         std::queue<EventDescription> m_eventQueue;
142         std::condition_variable m_waitCondition;
143
144         State m_state;
145         bool m_quit;
146 };
147
148 } // namespace CKM
149
150 #endif // _CENT_KEY_SERVICE_THREAD_