comparison UnitTestsSources/TestMessageBroker2_connect_ok.cpp @ 299:3897f9f28cfa am-callable-and-promise

backup work in progress: updated messaging framework with ICallable
author am@osimis.io
date Fri, 14 Sep 2018 16:44:01 +0200
parents
children b70e9be013e4
comparison
equal deleted inserted replaced
298:f58bfb7bbcc9 299:3897f9f28cfa
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "gtest/gtest.h"
23
24 #include <boost/noncopyable.hpp>
25 #include <boost/function.hpp>
26 #include <boost/bind.hpp>
27
28 #include <string>
29 #include <map>
30 #include <set>
31
32 int testCounter = 0;
33 namespace {
34
35 enum MessageType
36 {
37 // used in unit tests only
38 MessageType_Test1,
39 MessageType_Test2,
40
41 MessageType_LastGenericStoneMessage
42 };
43
44 struct IMessage : public boost::noncopyable
45 {
46 MessageType messageType_;
47 public:
48 IMessage(const MessageType& messageType)
49 : messageType_(messageType)
50 {}
51 virtual ~IMessage() {}
52
53 MessageType GetType() const {return messageType_;}
54 };
55
56
57 class IObserver;
58 class IObservable;
59
60 /*
61 * This is a central message broker. It keeps track of all observers and knows
62 * when an observer is deleted.
63 * This way, it can prevent an observable to send a message to a dead observer.
64 */
65 class MessageBroker : public boost::noncopyable
66 {
67
68 std::set<IObserver*> activeObservers_; // the list of observers that are currently alive (that have not been deleted)
69
70 public:
71
72 void Register(IObserver& observer)
73 {
74 activeObservers_.insert(&observer);
75 }
76
77 void Unregister(IObserver& observer)
78 {
79 activeObservers_.erase(&observer);
80 }
81
82 void EmitMessage(IObservable& from, std::set<IObserver*> observers, const IMessage& message);
83 };
84
85
86 class IObserver : public boost::noncopyable
87 {
88 protected:
89 MessageBroker& broker_;
90
91 public:
92 IObserver(MessageBroker& broker)
93 : broker_(broker)
94 {
95 broker_.Register(*this);
96 }
97
98 virtual ~IObserver()
99 {
100 broker_.Unregister(*this);
101 }
102
103 void HandleMessage_(IObservable &from, const IMessage &message)
104 {
105
106 HandleMessage(from, message);
107 }
108
109 virtual void HandleMessage(IObservable& from, const IMessage& message) = 0;
110
111
112 protected:
113
114
115 };
116
117 // struct ICallableObserver
118 // {
119 // IObserver* observer;
120 // };
121
122 // typedef void (IObserver::*ObserverSingleMesssageHandler)(IObservable& from, const IMessage& message);
123
124 // template <typename TObserver>
125 // struct CallableObserver : public ICallableObserver
126 // {
127 // void (TObserver::*ptrToMemberHandler)(IObservable& from, const IMessage& message);
128 // };
129
130 struct CallableObserver
131 {
132 IObserver* observer;
133 boost::function<void (IObservable& from, const IMessage& message)> f;
134 };
135
136 class IObservable : public boost::noncopyable
137 {
138 protected:
139 MessageBroker& broker_;
140
141 std::set<IObserver*> observers_;
142
143 std::map<MessageType, std::set<CallableObserver*> > callables_;
144 public:
145
146 IObservable(MessageBroker& broker)
147 : broker_(broker)
148 {
149 }
150 virtual ~IObservable()
151 {
152 }
153
154 void EmitMessage(const IMessage& message)
155 {
156 //broker_.EmitMessage(*this, observers_, message);
157
158 // TODO check if observer is still alive and call !
159 CallableObserver* callable = *(callables_[message.GetType()].begin());
160 callable->f(*this, message);
161 }
162
163 void RegisterObserver(IObserver& observer)
164 {
165 observers_.insert(&observer);
166 }
167
168 void UnregisterObserver(IObserver& observer)
169 {
170 observers_.erase(&observer);
171 }
172
173
174 //template<typename TObserver> void Connect(MessageType messageType, IObserver& observer, void (TObserver::*ptrToMemberHandler)(IObservable& from, const IMessage& message))
175 void Connect(MessageType messageType, IObserver& observer, boost::function<void (IObservable& from, const IMessage& message)> f)
176 {
177 callables_[messageType] = std::set<CallableObserver*>();
178 CallableObserver* callable = new CallableObserver();
179 callable->observer = &observer;
180 callable->f = f;
181 callables_[messageType].insert(callable);
182 }
183 };
184
185
186 class MyObservable : public IObservable
187 {
188 public:
189 MyObservable(MessageBroker& broker)
190 : IObservable(broker)
191 {}
192 };
193
194 class MyObserver : public IObserver
195 {
196 public:
197 MyObserver(MessageBroker& broker)
198 : IObserver(broker)
199 {}
200 virtual void HandleMessage(IObservable& from, const IMessage& message) {}
201 void HandleSpecificMessage(IObservable& from, const IMessage& message)
202 {
203 testCounter++;
204 }
205
206 };
207
208 }
209
210 //#define STONE_CONNECT(observabe, messageType, observerPtr, observerMemberFnPtr)
211
212 TEST(MessageBroker2, Test1)
213 {
214 MessageBroker broker;
215 MyObservable observable(broker);
216 MyObserver observer(broker);
217
218
219 observable.Connect(MessageType_Test1, observer, boost::bind(&MyObserver::HandleSpecificMessage, &observer, _1, _2));
220 //STONE_CONNECT(observable, MessageType_Test1, observer, &MyObserver::HandleSpecificMessage)
221 observable.EmitMessage(IMessage(MessageType_Test1));
222
223 ASSERT_EQ(1, testCounter);
224 }
225
226