Add MessageService
[platform/core/security/key-manager.git] / src / manager / main / message-service.h
1 /*
2  *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16 /*
17  * @file       message-service.h
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21
22 #pragma once
23
24 #include <mutex>
25 #include <list>
26 #include <utility>
27 #include <thread-service.h>
28 #include <noncopyable.h>
29 #include <dpl/log/log.h>
30
31 namespace CKM {
32
33 /*
34  * MessageService framework is a wrapper for inter service communication with use of
35  * CommunicationManager. It allows registering a service as a listener in CommunicationManager and
36  * provides thread safe message handling. The message received from communication manager in
37  * SENDER THREAD is passed to RECEIVER THREAD. The RECEIVER THREAD is notified with
38  * ServiceThread::CreateEvent which in turn calls provided callback in this thread.
39  */
40
41 template <typename ...Msgs>
42 class MessageService;
43
44
45 // aggregating template
46 template <typename Msg, typename ...Msgs>
47 class MessageService<Msg, Msgs...> : public MessageService<Msg>, public MessageService<Msgs...>
48 {
49 protected:
50     // RECEIVER THREAD
51     template <typename Mgr>
52     void Register(Mgr& mgr) {
53         MessageService<Msg>::Register(mgr);
54         MessageService<Msgs...>::Register(mgr);
55     }
56     // RECEIVER THREAD
57     void CheckMessages() {
58         MessageService<Msg>::CheckMessages();
59         MessageService<Msgs...>::CheckMessages();
60     }
61 };
62
63
64 // single Message type (Msg) handler
65 template <typename Msg>
66 class MessageService<Msg>
67 {
68 public:
69     MessageService() {}
70     virtual ~MessageService() {}
71     NONCOPYABLE(MessageService);
72
73 protected:
74     // RECEIVER THREAD: register as a listener of Msg
75     template <typename Mgr>
76     void Register(Mgr& mgr);
77
78     // SENDER THREAD: notify about new message
79     virtual void Notify() = 0;
80
81     // RECEIVER THREAD: check if there are new messages and process each of them
82     void CheckMessages();
83
84     // RECEIVER THREAD: process single message
85     virtual void ProcessMessage(Msg msg) = 0;
86
87 private:
88     // SENDER THREAD: add message to the list
89     void AddMessage(const Msg& msg);
90
91     std::mutex m_messagesMutex;
92     std::list<Msg> m_messages;
93 };
94
95 template <typename Msg>
96 template <typename Mgr>
97 void MessageService<Msg>::Register(Mgr& mgr)
98 {
99     mgr.Register<Msg>([this](const Msg& msg) { this->AddMessage(msg); });
100 }
101
102 template <typename Msg>
103 void MessageService<Msg>::AddMessage(const Msg& msg)
104 {
105     m_messagesMutex.lock();
106     m_messages.push_back(msg);
107     m_messagesMutex.unlock();
108     Notify(); // notify about added message
109 }
110
111 template <typename Msg>
112 void MessageService<Msg>::CheckMessages()
113 {
114     while(true) {
115         m_messagesMutex.lock();
116         if (m_messages.empty()) {
117             m_messagesMutex.unlock();
118             break;
119         }
120         // move out the first message
121         Msg message = std::move(m_messages.front());
122         m_messages.pop_front();
123         m_messagesMutex.unlock();
124
125         try {
126             ProcessMessage(std::move(message));
127         } catch(...) {
128             LogError("Uncaught exception in ProcessMessage");
129         }
130     }
131 }
132
133
134 // thread based service with messages support
135 template <typename ...Msgs>
136 class ThreadMessageService : public ThreadService, public MessageService<Msgs...>
137 {
138 public:
139     ThreadMessageService() {}
140     virtual ~ThreadMessageService() {}
141     NONCOPYABLE(ThreadMessageService);
142
143     // RECEIVER THREAD: register as a listener of all supported messages
144     template <typename Mgr>
145     void Register(Mgr& mgr) {
146         MessageService<Msgs...>::Register(mgr);
147     }
148
149 private:
150     // SENDER THREAD: adds callback to RECEIVER THREAD event queue and wakes it
151     virtual void Notify() {
152         CreateEvent([this]() { this->CheckMessages(); });
153     }
154
155     // RECEIVER THREAD
156     void CheckMessages() {
157         MessageService<Msgs...>::CheckMessages();
158     }
159 };
160
161 } /* namespace CKM */