Merge lp:~marcustomlinson/unity-scopes-api/scope_state_callback into lp:unity-scopes-api/devel

Proposed by Marcus Tomlinson
Status: Merged
Approved by: Pete Woods
Approved revision: 373
Merged at revision: 366
Proposed branch: lp:~marcustomlinson/unity-scopes-api/scope_state_callback
Merge into: lp:unity-scopes-api/devel
Diff against target: 993 lines (+334/-122)
25 files modified
debian/changelog (+7/-12)
debian/control (+1/-0)
debian/libunity-scopes1.symbols (+3/-2)
include/unity/scopes/Registry.h (+21/-2)
include/unity/scopes/internal/MWRegistry.h (+5/-2)
include/unity/scopes/internal/MWSubscriber.h (+4/-3)
include/unity/scopes/internal/RegistryImpl.h (+4/-1)
include/unity/scopes/internal/RegistryObject.h (+4/-3)
include/unity/scopes/internal/RegistryObjectBase.h (+1/-0)
include/unity/scopes/internal/smartscopes/SSRegistryObject.h (+1/-0)
include/unity/scopes/internal/zmq_middleware/RegistryI.h (+4/-0)
include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h (+1/-0)
include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h (+2/-7)
include/unity/scopes/testing/MockRegistry.h (+9/-1)
src/scopes/internal/MWRegistry.cpp (+15/-16)
src/scopes/internal/MWSubscriber.cpp (+5/-0)
src/scopes/internal/RegistryImpl.cpp (+13/-3)
src/scopes/internal/RegistryObject.cpp (+53/-27)
src/scopes/internal/smartscopes/SSRegistryObject.cpp (+5/-0)
src/scopes/internal/zmq_middleware/RegistryI.cpp (+24/-1)
src/scopes/internal/zmq_middleware/ZmqRegistry.cpp (+34/-0)
src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp (+4/-16)
src/scopes/internal/zmq_middleware/capnproto/Registry.capnp (+14/-0)
test/gtest/scopes/Registry/Registry_test.cpp (+96/-22)
test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp (+4/-4)
To merge this branch: bzr merge lp:~marcustomlinson/unity-scopes-api/scope_state_callback
Reviewer Review Type Date Requested Status
Pete Woods (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+221247@code.launchpad.net

Commit message

Introduced is_scope_running() and set_scope_state_callback() to Registry, added return values to set_*_callback() methods (to disconnect callback on destruction), and updated tests.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Pete Woods (pete-woods) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2014-05-29 14:08:41 +0000
3+++ debian/changelog 2014-06-03 08:58:50 +0000
4@@ -1,19 +1,14 @@
5-unity-scopes-api (0.4.8+14.10.20140519-0ubuntu1) UNRELEASED; urgency=medium
6+unity-scopes-api (0.4.8-0ubuntu1) UNRELEASED; urgency=medium
7+
8+ [ Pawel Stolowski ]
9+ * Changes to departments API.
10
11 [ Marcus Tomlinson ]
12 * Introduced Dir/ScopesWatcher classes to watch for updates to the scope install directories.
13- * Updated scoperegistry to inform the registry object when scopes are (un)installed.
14 * Updated all relevant registry classes to propagate an update pub/sub message via middleware.
15- * Added set_update_callback() to Registry (callback executed when the scopes list changes).
16-
17- -- Marcus Tomlinson <marcustomlinson@ubuntu> Thu, 22 May 2014 06:47:28 +0200
18-
19-unity-scopes-api (0.4.8-0ubuntu1) UNRELEASED; urgency=medium
20-
21- [ Pawel Stolowski ]
22- * Changes to departments API.
23-
24- -- Pawel Stolowski <pawel.stolowski@ubuntu.com> Tue, 20 May 2014 16:40:56 +0200
25+ * Added is_scope_running(), set_scope_state_callback() and set_update_callback() to Registry.
26+
27+ -- Marcus Tomlinson <marcustomlinson@ubuntu> Wed, 28 May 2014 17:08:45 +0200
28
29 unity-scopes-api (0.4.7+14.10.20140522-0ubuntu1) utopic; urgency=low
30
31
32=== modified file 'debian/control'
33--- debian/control 2014-05-22 17:52:29 +0000
34+++ debian/control 2014-06-03 08:58:50 +0000
35@@ -49,6 +49,7 @@
36 Multi-Arch: same
37 Pre-Depends: ${misc:Pre-Depends},
38 Depends: libunity-scopes1 (= ${binary:Version}),
39+ libproperties-cpp-dev,
40 libunity-api-dev,
41 ${misc:Depends},
42 Description: Header files for Unity scopes API
43
44=== modified file 'debian/libunity-scopes1.symbols'
45--- debian/libunity-scopes1.symbols 2014-05-30 13:21:46 +0000
46+++ debian/libunity-scopes1.symbols 2014-06-03 08:58:50 +0000
47@@ -418,6 +418,7 @@
48 (c++)"unity::scopes::internal::smartscopes::SSScopeObject::SSScopeObject(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::internal::MiddlewareBase>, std::shared_ptr<unity::scopes::internal::smartscopes::SSRegistryObject>)@Base" 0.4.0+14.04.20140312.1
49 (c++)"unity::scopes::internal::smartscopes::SSScopeObject::~SSScopeObject()@Base" 0.4.0+14.04.20140312.1
50 (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::refresh_thread()@Base" 0.4.0+14.04.20140312.1
51+ (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::is_scope_running(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme
52 (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::get_remote_scopes()@Base" 0.4.0+14.04.20140312.1
53 (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::add(unity::scopes::internal::smartscopes::RemoteScope const&, unity::scopes::ScopeMetadata const&, std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::ScopeMetadata, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::ScopeMetadata> > >&, std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&)@Base" 0.4.0+14.04.20140324
54 (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::locate(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1
55@@ -438,9 +439,9 @@
56 (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::exec(core::posix::ChildProcess::DeathObserver&, std::shared_ptr<unity::scopes::internal::Executor>)@Base" 0.4.3+14.10.20140428
57 (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::kill(std::unique_lock<std::mutex>&)@Base" 0.4.2+14.04.20140404.2
58 (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::kill()@Base" 0.4.2+14.04.20140404.2
59- (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeExecData)@Base" 0.4.2+14.04.20140404.2
60+ (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeExecData, std::shared_ptr<unity::scopes::internal::MWPublisher>)@Base" 0replaceme
61 (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeProcess const&)@Base" 0.4.2+14.04.20140404.2
62- (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeExecData)@Base" 0.4.2+14.04.20140404.2
63+ (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeExecData, std::shared_ptr<unity::scopes::internal::MWPublisher>)@Base" 0replaceme
64 (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeProcess const&)@Base" 0.4.2+14.04.20140404.2
65 (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::~ScopeProcess()@Base" 0.4.2+14.04.20140404.2
66 (c++)"unity::scopes::internal::RegistryObject::ScopeExecData::~ScopeExecData()@Base" 0.4.2+14.04.20140404.2
67
68=== modified file 'include/unity/scopes/Registry.h'
69--- include/unity/scopes/Registry.h 2014-05-27 07:08:33 +0000
70+++ include/unity/scopes/Registry.h 2014-06-03 08:58:50 +0000
71@@ -19,6 +19,7 @@
72 #ifndef UNITY_SCOPES_REGISTRY_H
73 #define UNITY_SCOPES_REGISTRY_H
74
75+#include <core/signal.h>
76 #include <unity/scopes/Object.h>
77 #include <unity/scopes/RegistryProxyFwd.h>
78 #include <unity/scopes/ScopeMetadata.h>
79@@ -56,8 +57,9 @@
80
81 /**
82 \brief Returns the metadata for the scope with the given ID.
83+ \param scope_id The ID of the scope from which we wish to retrieve metadata.
84 \return The metadata for the scope.
85- \throws NotFoundException if no scope with the given name exists.
86+ \throws NotFoundException if no scope with the given ID exists.
87 */
88 virtual ScopeMetadata get_metadata(std::string const& scope_id) = 0;
89
90@@ -75,13 +77,30 @@
91 virtual MetadataMap list_if(std::function<bool(ScopeMetadata const& item)> predicate) = 0;
92
93 /**
94+ \brief Returns whether a scope is currently running or not.
95+ \param scope_id The ID of the scope from which we wish to retrieve state.
96+ \return True if the scope is running, and False if it is not running.
97+ \throws NotFoundException if no scope with the given ID exists.
98+ */
99+ virtual bool is_scope_running(std::string const& scope_id) = 0;
100+
101+ /**
102+ \brief Assigns a callback method to be executed when a scope's running state (started / stopped) changes.
103+ \param scope_id The ID of the scope from which we wish to retrieve state changes.
104+ \param callback The function object that is invoked when a scope changes running state.
105+ \throws MiddlewareException if the registry subscriber failed to initialize.
106+ */
107+ virtual core::ScopedConnection set_scope_state_callback(std::string const& scope_id, std::function<void(bool is_running)> callback) = 0;
108+
109+ /**
110 \brief Assigns a callback method to be executed when the registry's scope list changes.
111
112 Note: Upon receiving this callback, you should retrieve the updated scopes list via the list() method if
113 you wish to retain synchronisation between client and server.
114 \param callback The function object that is invoked when an update occurs.
115+ \throws MiddlewareException if the registry subscriber failed to initialize.
116 */
117- virtual void set_list_update_callback(std::function<void()> callback) = 0;
118+ virtual core::ScopedConnection set_list_update_callback(std::function<void()> callback) = 0;
119
120 protected:
121 /// @cond
122
123=== modified file 'include/unity/scopes/internal/MWRegistry.h'
124--- include/unity/scopes/internal/MWRegistry.h 2014-05-27 07:08:33 +0000
125+++ include/unity/scopes/internal/MWRegistry.h 2014-06-03 08:58:50 +0000
126@@ -40,18 +40,21 @@
127 virtual ScopeMetadata get_metadata(std::string const& scope_id) = 0;
128 virtual MetadataMap list() = 0;
129 virtual ObjectProxy locate(std::string const& identity) = 0;
130+ virtual bool is_scope_running(std::string const& scope_id) = 0;
131
132 virtual ~MWRegistry();
133
134 // Local operations
135- void set_list_update_callback(std::function<void()> callback);
136+ core::ScopedConnection set_scope_state_callback(std::string const& scope_id, std::function<void(bool)> callback);
137+ core::ScopedConnection set_list_update_callback(std::function<void()> callback);
138
139 protected:
140 MWRegistry(MiddlewareBase* mw_base);
141
142 private:
143 MiddlewareBase* mw_base_;
144- MWSubscriber::UPtr subscriber_;
145+ MWSubscriber::UPtr list_update_subscriber_;
146+ std::map<std::string, MWSubscriber::UPtr> scope_state_subscribers_;
147 };
148
149 } // namespace internal
150
151=== modified file 'include/unity/scopes/internal/MWSubscriber.h'
152--- include/unity/scopes/internal/MWSubscriber.h 2014-05-19 05:15:06 +0000
153+++ include/unity/scopes/internal/MWSubscriber.h 2014-06-03 08:58:50 +0000
154@@ -19,6 +19,7 @@
155 #ifndef UNITY_SCOPES_INTERNAL_MWSUBSCRIBER_H
156 #define UNITY_SCOPES_INTERNAL_MWSUBSCRIBER_H
157
158+#include <core/signal.h>
159 #include <unity/util/DefinesPtrs.h>
160 #include <unity/util/NonCopyable.h>
161
162@@ -31,8 +32,6 @@
163 namespace internal
164 {
165
166-typedef std::function<void(std::string const& message)> SubscriberCallback;
167-
168 class MWSubscriber
169 {
170 public:
171@@ -42,10 +41,12 @@
172 virtual ~MWSubscriber();
173
174 virtual std::string endpoint() const = 0;
175- virtual void set_message_callback(SubscriberCallback callback) = 0;
176+ core::Signal<std::string const&> const& message_received() const;
177
178 protected:
179 MWSubscriber();
180+
181+ core::Signal<std::string const&> message_received_;
182 };
183
184 } // namespace internal
185
186=== modified file 'include/unity/scopes/internal/RegistryImpl.h'
187--- include/unity/scopes/internal/RegistryImpl.h 2014-05-27 07:08:33 +0000
188+++ include/unity/scopes/internal/RegistryImpl.h 2014-06-03 08:58:50 +0000
189@@ -43,7 +43,10 @@
190 virtual ScopeMetadata get_metadata(std::string const& scope_id) override;
191 virtual MetadataMap list() override;
192 virtual MetadataMap list_if(std::function<bool(ScopeMetadata const& item)> predicate) override;
193- virtual void set_list_update_callback(std::function<void()> callback) override;
194+ virtual bool is_scope_running(std::string const& scope_id) override;
195+
196+ virtual core::ScopedConnection set_scope_state_callback(std::string const& scope_id, std::function<void(bool)> callback) override;
197+ virtual core::ScopedConnection set_list_update_callback(std::function<void()> callback) override;
198
199 // Remote operation. Not part of public API, hence not override.
200 ObjectProxy locate(std::string const& identity);
201
202=== modified file 'include/unity/scopes/internal/RegistryObject.h'
203--- include/unity/scopes/internal/RegistryObject.h 2014-05-27 09:54:38 +0000
204+++ include/unity/scopes/internal/RegistryObject.h 2014-06-03 08:58:50 +0000
205@@ -65,6 +65,7 @@
206 virtual ScopeMetadata get_metadata(std::string const& scope_id) const override;
207 virtual MetadataMap list() const override;
208 virtual ObjectProxy locate(std::string const& identity) override;
209+ virtual bool is_scope_running(std::string const& scope_id) override;
210
211 // Local methods
212 bool add_local_scope(std::string const& scope_id, ScopeMetadata const& scope,
213@@ -72,7 +73,6 @@
214 bool remove_local_scope(std::string const& scope_id);
215 void set_remote_registry(MWRegistryProxy const& remote_registry);
216
217- bool is_scope_running(std::string const& scope_id);
218 StateReceiverObject::SPtr state_receiver();
219
220 private:
221@@ -87,7 +87,7 @@
222 Stopped, Starting, Running, Stopping
223 };
224
225- ScopeProcess(ScopeExecData exec_data);
226+ ScopeProcess(ScopeExecData exec_data, MWPublisher::SPtr publisher);
227 ScopeProcess(ScopeProcess const& other);
228 ~ScopeProcess();
229
230@@ -115,6 +115,7 @@
231 mutable std::mutex process_mutex_;
232 mutable std::condition_variable state_change_cond_;
233 core::posix::ChildProcess process_ = core::posix::ChildProcess::invalid();
234+ MWPublisher::SPtr reg_publisher_;
235 };
236
237 private:
238@@ -132,7 +133,7 @@
239 MWRegistryProxy remote_registry_;
240 mutable std::mutex mutex_;
241
242- MWPublisher::UPtr publisher_;
243+ MWPublisher::SPtr publisher_;
244 };
245
246 } // namespace internal
247
248=== modified file 'include/unity/scopes/internal/RegistryObjectBase.h'
249--- include/unity/scopes/internal/RegistryObjectBase.h 2014-04-03 12:57:25 +0000
250+++ include/unity/scopes/internal/RegistryObjectBase.h 2014-06-03 08:58:50 +0000
251@@ -39,6 +39,7 @@
252 virtual ScopeMetadata get_metadata(std::string const& scope_id) const = 0;
253 virtual MetadataMap list() const = 0;
254 virtual ObjectProxy locate(std::string const& identity) = 0;
255+ virtual bool is_scope_running(std::string const& scope_id) = 0;
256 };
257
258 } // namespace internal
259
260=== modified file 'include/unity/scopes/internal/smartscopes/SSRegistryObject.h'
261--- include/unity/scopes/internal/smartscopes/SSRegistryObject.h 2014-05-09 05:26:39 +0000
262+++ include/unity/scopes/internal/smartscopes/SSRegistryObject.h 2014-06-03 08:58:50 +0000
263@@ -54,6 +54,7 @@
264 MetadataMap list() const override;
265
266 ObjectProxy locate(std::string const& identity) override;
267+ bool is_scope_running(std::string const& scope_id) override;
268
269 bool has_scope(std::string const& scope_id) const;
270 std::string get_base_url(std::string const& scope_id) const;
271
272=== modified file 'include/unity/scopes/internal/zmq_middleware/RegistryI.h'
273--- include/unity/scopes/internal/zmq_middleware/RegistryI.h 2014-04-03 12:57:25 +0000
274+++ include/unity/scopes/internal/zmq_middleware/RegistryI.h 2014-06-03 08:58:50 +0000
275@@ -59,6 +59,10 @@
276 virtual void locate_(Current const& current,
277 capnp::AnyPointer::Reader& in_params,
278 capnproto::Response::Builder& r);
279+
280+ virtual void is_scope_running_(Current const& current,
281+ capnp::AnyPointer::Reader& in_params,
282+ capnproto::Response::Builder& r);
283 };
284
285 } // namespace zmq_middleware
286
287=== modified file 'include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h'
288--- include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h 2014-04-03 12:57:25 +0000
289+++ include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h 2014-06-03 08:58:50 +0000
290@@ -52,6 +52,7 @@
291 virtual ScopeMetadata get_metadata(std::string const& scope_id) override;
292 virtual MetadataMap list() override;
293 virtual ObjectProxy locate(std::string const& identity) override;
294+ virtual bool is_scope_running(std::string const& scope_id) override;
295 };
296
297 } // namespace zmq_middleware
298
299=== modified file 'include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h'
300--- include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h 2014-05-21 10:45:51 +0000
301+++ include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h 2014-06-03 08:58:50 +0000
302@@ -19,13 +19,11 @@
303 #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSUBSCRIBER_H
304 #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSUBSCRIBER_H
305
306+#include <condition_variable>
307+#include <thread>
308 #include <unity/scopes/internal/MWSubscriber.h>
309-
310 #include <zmqpp/context.hpp>
311
312-#include <condition_variable>
313-#include <thread>
314-
315 namespace unity
316 {
317
318@@ -48,7 +46,6 @@
319 virtual ~ZmqSubscriber();
320
321 std::string endpoint() const override;
322- void set_message_callback(SubscriberCallback callback) override;
323
324 private:
325 enum ThreadState
326@@ -70,8 +67,6 @@
327 ThreadState thread_state_;
328 std::exception_ptr thread_exception_;
329
330- SubscriberCallback callback_;
331-
332 void subscriber_thread();
333 };
334
335
336=== modified file 'include/unity/scopes/testing/MockRegistry.h'
337--- include/unity/scopes/testing/MockRegistry.h 2014-05-27 07:08:33 +0000
338+++ include/unity/scopes/testing/MockRegistry.h 2014-06-03 08:58:50 +0000
339@@ -43,7 +43,15 @@
340 MOCK_METHOD1(get_metadata, ScopeMetadata(std::string const&));
341 MOCK_METHOD0(list, MetadataMap());
342 MOCK_METHOD1(list_if, MetadataMap(std::function<bool(ScopeMetadata const&)>));
343- MOCK_METHOD1(set_list_update_callback, void(std::function<void()>));
344+ MOCK_METHOD1(is_scope_running, bool(std::string const&));
345+ core::ScopedConnection set_scope_state_callback(std::string const&, std::function<void(bool is_running)>) override
346+ {
347+ return core::Signal<>().connect([]{});
348+ }
349+ core::ScopedConnection set_list_update_callback(std::function<void()>) override
350+ {
351+ return core::Signal<>().connect([]{});
352+ }
353 };
354
355 /// @endcond
356
357=== modified file 'src/scopes/internal/MWRegistry.cpp'
358--- src/scopes/internal/MWRegistry.cpp 2014-05-27 07:08:33 +0000
359+++ src/scopes/internal/MWRegistry.cpp 2014-06-03 08:58:50 +0000
360@@ -41,24 +41,23 @@
361 {
362 }
363
364-void MWRegistry::set_list_update_callback(std::function<void()> callback)
365-{
366- if (!subscriber_)
367+core::ScopedConnection MWRegistry::set_scope_state_callback(std::string const& scope_id, std::function<void(bool)> callback)
368+{
369+ if (scope_state_subscribers_.find(scope_id) == scope_state_subscribers_.end())
370+ {
371+ scope_state_subscribers_[scope_id] = mw_base_->create_subscriber(mw_base_->runtime()->registry_identity(), scope_id);
372+ }
373+ return scope_state_subscribers_.at(scope_id)->message_received().connect([callback](string const& state){ callback(state == "started"); });
374+}
375+
376+core::ScopedConnection MWRegistry::set_list_update_callback(std::function<void()> callback)
377+{
378+ if (!list_update_subscriber_)
379 {
380 // Use lazy initialization here to only subscribe to the publisher if a callback is set
381- try
382- {
383- subscriber_ = mw_base_->create_subscriber(mw_base_->runtime()->registry_identity());
384- }
385- catch (std::exception const& e)
386- {
387- cerr << "MWRegistry::set_list_update_callback(): failed to create registry subscriber: " << e.what() << endl;
388- }
389- }
390- if (subscriber_)
391- {
392- subscriber_->set_message_callback([callback](string const&){ callback(); });
393- }
394+ list_update_subscriber_ = mw_base_->create_subscriber(mw_base_->runtime()->registry_identity());
395+ }
396+ return list_update_subscriber_->message_received().connect([callback](string const&){ callback(); });
397 }
398
399 } // namespace internal
400
401=== modified file 'src/scopes/internal/MWSubscriber.cpp'
402--- src/scopes/internal/MWSubscriber.cpp 2014-05-14 12:57:34 +0000
403+++ src/scopes/internal/MWSubscriber.cpp 2014-06-03 08:58:50 +0000
404@@ -35,6 +35,11 @@
405 {
406 }
407
408+core::Signal<std::string const&> const& MWSubscriber::message_received() const
409+{
410+ return message_received_;
411+}
412+
413 } // namespace internal
414
415 } // namespace scopes
416
417=== modified file 'src/scopes/internal/RegistryImpl.cpp'
418--- src/scopes/internal/RegistryImpl.cpp 2014-05-27 07:08:33 +0000
419+++ src/scopes/internal/RegistryImpl.cpp 2014-06-03 08:58:50 +0000
420@@ -71,9 +71,19 @@
421 return matching_entries;
422 }
423
424-void RegistryImpl::set_list_update_callback(std::function<void()> callback)
425-{
426- fwd()->set_list_update_callback(callback);
427+bool RegistryImpl::is_scope_running(std::string const& scope_id)
428+{
429+ return fwd()->is_scope_running(scope_id);
430+}
431+
432+core::ScopedConnection RegistryImpl::set_scope_state_callback(std::string const& scope_id, std::function<void(bool)> callback)
433+{
434+ return fwd()->set_scope_state_callback(scope_id, callback);
435+}
436+
437+core::ScopedConnection RegistryImpl::set_list_update_callback(std::function<void()> callback)
438+{
439+ return fwd()->set_list_update_callback(callback);
440 }
441
442 MWRegistryProxy RegistryImpl::fwd()
443
444=== modified file 'src/scopes/internal/RegistryObject.cpp'
445--- src/scopes/internal/RegistryObject.cpp 2014-05-27 09:54:38 +0000
446+++ src/scopes/internal/RegistryObject.cpp 2014-06-03 08:58:50 +0000
447@@ -199,6 +199,19 @@
448 return proxy;
449 }
450
451+bool RegistryObject::is_scope_running(std::string const& scope_id)
452+{
453+ lock_guard<decltype(mutex_)> lock(mutex_);
454+
455+ auto it = scope_processes_.find(scope_id);
456+ if (it != scope_processes_.end())
457+ {
458+ return it->second.state() != ScopeProcess::ProcessState::Stopped;
459+ }
460+
461+ throw NotFoundException("RegistryObject::is_scope_process_running(): no such scope: ", scope_id);
462+}
463+
464 bool RegistryObject::add_local_scope(std::string const& scope_id, ScopeMetadata const& metadata,
465 ScopeExecData const& exec_data)
466 {
467@@ -221,7 +234,7 @@
468 return_value = false;
469 }
470 scopes_.insert(make_pair(scope_id, metadata));
471- scope_processes_.insert(make_pair(scope_id, ScopeProcess(exec_data)));
472+ scope_processes_.insert(make_pair(scope_id, ScopeProcess(exec_data, publisher_)));
473
474 if (publisher_)
475 {
476@@ -263,19 +276,6 @@
477 remote_registry_ = remote_registry;
478 }
479
480-bool RegistryObject::is_scope_running(std::string const& scope_id)
481-{
482- lock_guard<decltype(mutex_)> lock(mutex_);
483-
484- auto it = scope_processes_.find(scope_id);
485- if (it != scope_processes_.end())
486- {
487- return it->second.state() != ScopeProcess::ProcessState::Stopped;
488- }
489-
490- throw NotFoundException("RegistryObject::is_scope_process_running(): no such scope: ", scope_id);
491-}
492-
493 StateReceiverObject::SPtr RegistryObject::state_receiver()
494 {
495 return state_receiver_;
496@@ -316,13 +316,15 @@
497 // simply ignore states from scopes the registry does not know about
498 }
499
500-RegistryObject::ScopeProcess::ScopeProcess(ScopeExecData exec_data)
501+RegistryObject::ScopeProcess::ScopeProcess(ScopeExecData exec_data, MWPublisher::SPtr publisher)
502 : exec_data_(exec_data)
503+ , reg_publisher_(publisher)
504 {
505 }
506
507 RegistryObject::ScopeProcess::ScopeProcess(ScopeProcess const& other)
508 : exec_data_(other.exec_data_)
509+ , reg_publisher_(other.reg_publisher_)
510 {
511 }
512
513@@ -468,27 +470,51 @@
514 {
515 return;
516 }
517- else if (state == Running && state_ != Starting)
518- {
519- cout << "RegistryObject::ScopeProcess: Process for scope: \"" << exec_data_.scope_id
520- << "\" started manually" << endl;
521-
522- // Don't update state, treat this scope as not running if a locate() is requested
523- return;
524+ else if (state == Running)
525+ {
526+ if (reg_publisher_)
527+ {
528+ // Send a "started" message to subscribers to inform them that this scope (topic) has started
529+ reg_publisher_->send_message("started", exec_data_.scope_id);
530+ }
531+
532+ if (state_ != Starting)
533+ {
534+ cout << "RegistryObject::ScopeProcess: Process for scope: \"" << exec_data_.scope_id
535+ << "\" started manually" << endl;
536+
537+ // Don't update state, treat this scope as not running if a locate() is requested
538+ return;
539+ }
540+ }
541+ else if (state == Stopped)
542+ {
543+ if (reg_publisher_)
544+ {
545+ // Send a "stopped" message to subscribers to inform them that this scope (topic) has stopped
546+ reg_publisher_->send_message("stopped", exec_data_.scope_id);
547+ }
548+
549+ if (state_ != Stopping)
550+ {
551+ cerr << "RegistryObject::ScopeProcess: Scope: \"" << exec_data_.scope_id
552+ << "\" closed unexpectedly. Either the process crashed or was killed forcefully." << endl;
553+ }
554 }
555 else if (state == Stopping && state_ != Running)
556 {
557+ if (reg_publisher_)
558+ {
559+ // Send a "stopped" message to subscribers to inform them that this scope (topic) has stopped
560+ reg_publisher_->send_message("stopped", exec_data_.scope_id);
561+ }
562+
563 cout << "RegistryObject::ScopeProcess: Manually started process for scope: \""
564 << exec_data_.scope_id << "\" terminated" << endl;
565
566 // Don't update state, treat this scope as not running if a locate() is requested
567 return;
568 }
569- else if (state == Stopped && state_ != Stopping)
570- {
571- cerr << "RegistryObject::ScopeProcess: Scope: \"" << exec_data_.scope_id
572- << "\" closed unexpectedly. Either the process crashed or was killed forcefully." << endl;
573- }
574 state_ = state;
575 state_change_cond_.notify_all();
576 }
577
578=== modified file 'src/scopes/internal/smartscopes/SSRegistryObject.cpp'
579--- src/scopes/internal/smartscopes/SSRegistryObject.cpp 2014-05-16 14:29:11 +0000
580+++ src/scopes/internal/smartscopes/SSRegistryObject.cpp 2014-06-03 08:58:50 +0000
581@@ -127,6 +127,11 @@
582 throw internal::RegistryException("SSRegistryObject::locate(): operation not available");
583 }
584
585+bool SSRegistryObject::is_scope_running(std::string const&)
586+{
587+ throw internal::RegistryException("SSRegistryObject::is_scope_running(): operation not available");
588+}
589+
590 bool SSRegistryObject::has_scope(std::string const& scope_id) const
591 {
592 std::lock_guard<std::mutex> lock(scopes_mutex_);
593
594=== modified file 'src/scopes/internal/zmq_middleware/RegistryI.cpp'
595--- src/scopes/internal/zmq_middleware/RegistryI.cpp 2014-05-29 15:41:42 +0000
596+++ src/scopes/internal/zmq_middleware/RegistryI.cpp 2014-06-03 08:58:50 +0000
597@@ -68,7 +68,8 @@
598 RegistryI::RegistryI(RegistryObjectBase::SPtr const& ro) :
599 ServantBase(ro, { { "get_metadata", bind(&RegistryI::get_metadata_, this, _1, _2, _3) },
600 { "list", bind(&RegistryI::list_, this, _1, _2, _3) },
601- { "locate", bind(&RegistryI::locate_, this, _1, _2, _3) } })
602+ { "locate", bind(&RegistryI::locate_, this, _1, _2, _3) },
603+ { "is_scope_running", bind(&RegistryI::is_scope_running_, this, _1, _2, _3) } })
604
605 {
606 }
607@@ -151,6 +152,28 @@
608 }
609 }
610
611+void RegistryI::is_scope_running_(Current const&,
612+ capnp::AnyPointer::Reader& in_params,
613+ capnproto::Response::Builder& r)
614+{
615+ auto req = in_params.getAs<capnproto::Registry::IsScopeRunningRequest>();
616+ string scope_id = req.getIdentity().cStr();
617+ auto delegate = dynamic_pointer_cast<RegistryObjectBase>(del());
618+ try
619+ {
620+ auto is_running = delegate->is_scope_running(scope_id);
621+ r.setStatus(capnproto::ResponseStatus::SUCCESS);
622+ auto is_scope_running_response = r.initPayload().getAs<capnproto::Registry::IsScopeRunningResponse>().initResponse();
623+ is_scope_running_response.setReturnValue(is_running);
624+ }
625+ catch (NotFoundException const& e)
626+ {
627+ r.setStatus(capnproto::ResponseStatus::USER_EXCEPTION);
628+ auto get_metadata_response = r.initPayload().getAs<capnproto::Registry::IsScopeRunningResponse>().initResponse();
629+ get_metadata_response.initNotFoundException().setIdentity(e.name().c_str());
630+ }
631+}
632+
633 } // namespace zmq_middleware
634
635 } // namespace internal
636
637=== modified file 'src/scopes/internal/zmq_middleware/ZmqRegistry.cpp'
638--- src/scopes/internal/zmq_middleware/ZmqRegistry.cpp 2014-05-07 05:54:20 +0000
639+++ src/scopes/internal/zmq_middleware/ZmqRegistry.cpp 2014-06-03 08:58:50 +0000
640@@ -187,6 +187,40 @@
641 }
642 }
643 }
644+
645+bool ZmqRegistry::is_scope_running(std::string const& scope_id)
646+{
647+ capnp::MallocMessageBuilder request_builder;
648+ auto request = make_request_(request_builder, "is_scope_running");
649+ auto in_params = request.initInParams().getAs<capnproto::Registry::IsScopeRunningRequest>();
650+ in_params.setIdentity(scope_id.c_str());
651+
652+ auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_twoway_(request_builder); });
653+ auto receiver = future.get();
654+ auto segments = receiver.receive();
655+ capnp::SegmentArrayMessageReader reader(segments);
656+ auto response = reader.getRoot<capnproto::Response>();
657+ throw_if_runtime_exception(response);
658+
659+ auto is_scope_running_response = response.getPayload().getAs<capnproto::Registry::IsScopeRunningResponse>().getResponse();
660+ switch (is_scope_running_response.which())
661+ {
662+ case capnproto::Registry::IsScopeRunningResponse::Response::RETURN_VALUE:
663+ {
664+ return is_scope_running_response.getReturnValue();
665+ }
666+ case capnproto::Registry::IsScopeRunningResponse::Response::NOT_FOUND_EXCEPTION:
667+ {
668+ auto ex = is_scope_running_response.getNotFoundException();
669+ throw NotFoundException("Registry::is_scope_running(): no such scope", ex.getIdentity().cStr());
670+ }
671+ default:
672+ {
673+ throw MiddlewareException("Registry::is_scope_running(): unknown user exception");
674+ }
675+ }
676+}
677+
678 } // namespace zmq_middleware
679
680 } // namespace internal
681
682=== modified file 'src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp'
683--- src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp 2014-05-21 13:01:10 +0000
684+++ src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp 2014-06-03 08:58:50 +0000
685@@ -44,7 +44,6 @@
686 , topic_(topic)
687 , thread_state_(NotRunning)
688 , thread_exception_(nullptr)
689- , callback_(nullptr)
690 {
691 // Validate publisher_id
692 if (publisher_id.find('/') != std::string::npos)
693@@ -91,7 +90,6 @@
694 {
695 {
696 std::lock_guard<std::mutex> lock(mutex_);
697- callback_ = nullptr;
698 thread_stopper_ = nullptr;
699 }
700
701@@ -106,12 +104,6 @@
702 return endpoint_;
703 }
704
705-void ZmqSubscriber::set_message_callback(SubscriberCallback callback)
706-{
707- std::lock_guard<std::mutex> lock(mutex_);
708- callback_ = callback;
709-}
710-
711 void ZmqSubscriber::subscriber_thread()
712 {
713 try
714@@ -151,14 +143,11 @@
715
716 // Discard the message if no callback is set
717 std::lock_guard<std::mutex> lock(mutex_);
718- if (callback_)
719+ // Message should arrive in the format: "<topic>:<message>"
720+ if (message.length() > topic_.length() &&
721+ message[topic_.length()] == ':')
722 {
723- // Message should arrive in the format: "<topic>:<message>"
724- if (message.length() > topic_.length() &&
725- message[topic_.length()] == ':')
726- {
727- callback_(message.substr(topic_.length() + 1));
728- }
729+ message_received_(message.substr(topic_.length() + 1));
730 }
731 }
732 else if(poller.has_input(stop_socket))
733@@ -175,7 +164,6 @@
734 catch (...)
735 {
736 std::lock_guard<std::mutex> lock(mutex_);
737- callback_ = nullptr;
738 thread_stopper_ = nullptr;
739 thread_exception_ = std::current_exception();
740 thread_state_ = Stopped;
741
742=== modified file 'src/scopes/internal/zmq_middleware/capnproto/Registry.capnp'
743--- src/scopes/internal/zmq_middleware/capnproto/Registry.capnp 2014-04-03 12:57:25 +0000
744+++ src/scopes/internal/zmq_middleware/capnproto/Registry.capnp 2014-06-03 08:58:50 +0000
745@@ -80,3 +80,17 @@
746 registryException @2 : RegistryException;
747 }
748 }
749+
750+struct IsScopeRunningRequest
751+{
752+ identity @0 : Text;
753+}
754+
755+struct IsScopeRunningResponse
756+{
757+ response : union
758+ {
759+ returnValue @0 : Bool;
760+ notFoundException @1 : NotFoundException;
761+ }
762+}
763
764=== modified file 'test/gtest/scopes/Registry/Registry_test.cpp'
765--- test/gtest/scopes/Registry/Registry_test.cpp 2014-05-27 12:46:25 +0000
766+++ test/gtest/scopes/Registry/Registry_test.cpp 2014-06-03 08:58:50 +0000
767@@ -64,6 +64,7 @@
768 auto now = std::chrono::steady_clock::now();
769 auto expiry_time = now + std::chrono::seconds(5);
770 EXPECT_TRUE(cond_.wait_until(lock, expiry_time, [this]{ return done_; })) << "finished message not delivered";
771+ done_ = false;
772 return finished_ok_;
773 }
774
775@@ -103,43 +104,115 @@
776 EXPECT_EQ("scope-B.HotKey", meta.hot_key());
777 EXPECT_EQ("scope-B.SearchHint", meta.search_hint());
778 EXPECT_EQ(TEST_RUNTIME_PATH "/scopes/testscopeB", meta.scope_directory());
779-
780- auto sp = meta.proxy();
781+}
782+
783+TEST(Registry, scope_state_notify)
784+{
785+ bool update_received = false;
786+ bool testscopeA_state = false;
787+ bool testscopeB_state = false;
788+ std::mutex mutex;
789+ std::condition_variable cond;
790+
791+ Runtime::UPtr rt = Runtime::create(TEST_RUNTIME_FILE);
792+ RegistryProxy r = rt->registry();
793+
794+ // Configure testscopeA scope_state_callback
795+ auto connA = r->set_scope_state_callback("testscopeA", [&update_received, &testscopeA_state, &mutex, &cond](bool is_running)
796+ {
797+ std::lock_guard<std::mutex> lock(mutex);
798+ update_received = true;
799+ testscopeA_state = is_running;
800+ cond.notify_one();
801+ });
802+ // Configure testscopeB scope_state_callback
803+ auto connB = r->set_scope_state_callback("testscopeB", [&update_received, &testscopeB_state, &mutex, &cond](bool is_running)
804+ {
805+ std::lock_guard<std::mutex> lock(mutex);
806+ update_received = true;
807+ testscopeB_state = is_running;
808+ cond.notify_one();
809+ });
810+ auto wait_for_state_update = [&update_received, &mutex, &cond]
811+ {
812+ // Wait for an update notification
813+ std::unique_lock<std::mutex> lock(mutex);
814+ bool success = cond.wait_for(lock, std::chrono::milliseconds(500), [&update_received] { return update_received; });
815+ update_received = false;
816+ return success;
817+ };
818
819 auto receiver = std::make_shared<Receiver>();
820 SearchListenerBase::SPtr reply(receiver);
821 SearchMetadata metadata("C", "desktop");
822
823+ auto meta = r->get_metadata("testscopeA");
824+ auto sp = meta.proxy();
825+
826+ // testscopeA should not be running at this point
827+ EXPECT_FALSE(r->is_scope_running("testscopeA"));
828+ EXPECT_FALSE(wait_for_state_update());
829+
830+ // search would fail if testscopeA can't be executed
831+ auto ctrl = sp->search("foo", metadata, reply);
832+ EXPECT_TRUE(receiver->wait_until_finished());
833+
834+ // testscopeA should now be running
835+ EXPECT_TRUE(wait_for_state_update());
836+ EXPECT_TRUE(testscopeA_state);
837+ EXPECT_TRUE(r->is_scope_running("testscopeA"));
838+
839+ meta = r->get_metadata("testscopeB");
840+ sp = meta.proxy();
841+
842+ // testscopeB should not be running at this point
843+ EXPECT_FALSE(r->is_scope_running("testscopeB"));
844+ EXPECT_FALSE(wait_for_state_update());
845+
846 // search would fail if testscopeB can't be executed
847- auto ctrl = sp->search("foo", metadata, reply);
848+ ctrl = sp->search("foo", metadata, reply);
849 EXPECT_TRUE(receiver->wait_until_finished());
850+
851+ // testscopeB should now be running
852+ EXPECT_TRUE(wait_for_state_update());
853+ EXPECT_TRUE(testscopeB_state);
854+ EXPECT_TRUE(r->is_scope_running("testscopeB"));
855+
856+ // check now that we get a callback when testscopeB terminates (timed out after 2s)
857+ std::this_thread::sleep_for(std::chrono::seconds{3});
858+ EXPECT_TRUE(wait_for_state_update());
859+ EXPECT_FALSE(testscopeB_state);
860+ EXPECT_FALSE(r->is_scope_running("testscopeB"));
861 }
862
863-TEST(Registry, update_notify)
864+TEST(Registry, list_update_notify)
865 {
866- bool update_received_ = false;
867- std::mutex mutex_;
868- std::condition_variable cond_;
869+ bool update_received = false;
870+ std::mutex mutex;
871+ std::condition_variable cond;
872
873 Runtime::UPtr rt = Runtime::create(TEST_RUNTIME_FILE);
874 RegistryProxy r = rt->registry();
875
876 // Configure registry update callback
877- r->set_list_update_callback([&update_received_, &mutex_, &cond_]
878+ auto conn = r->set_list_update_callback([&update_received, &mutex, &cond]
879 {
880- std::lock_guard<std::mutex> lock(mutex_);
881- update_received_ = true;
882- cond_.notify_one();
883+ std::lock_guard<std::mutex> lock(mutex);
884+ update_received = true;
885+ cond.notify_one();
886 });
887- auto wait_for_update = [&update_received_, &mutex_, &cond_]
888+ auto wait_for_update = [&update_received, &mutex, &cond]
889 {
890 // Flush out update notifications
891- std::unique_lock<std::mutex> lock(mutex_);
892- while (cond_.wait_for(lock, std::chrono::milliseconds(500), [&update_received_] { return update_received_; }))
893+ std::unique_lock<std::mutex> lock(mutex);
894+ bool success = false;
895+ while (cond.wait_for(lock, std::chrono::milliseconds(500), [&update_received] { return update_received; }))
896 {
897- update_received_ = false;
898+ success = true;
899+ update_received = false;
900 }
901- update_received_ = false;
902+ update_received = false;
903+ return success;
904 };
905
906 system::error_code ec;
907@@ -156,7 +229,7 @@
908 std::cout << "Move testscopeC into the scopes folder" << std::endl;
909 filesystem::rename(TEST_RUNTIME_PATH "/other_scopes/testscopeC", TEST_RUNTIME_PATH "/scopes/testscopeC", ec);
910 ASSERT_EQ("Success", ec.message());
911- wait_for_update();
912+ EXPECT_TRUE(wait_for_update());
913
914 // Now check that we have 3 scopes registered
915 list = r->list();
916@@ -170,7 +243,7 @@
917 std::cout << "Make a symlink to testscopeD in the scopes folder" << std::endl;
918 filesystem::create_symlink(TEST_RUNTIME_PATH "/other_scopes/testscopeD", TEST_RUNTIME_PATH "/scopes/testscopeD", ec);
919 ASSERT_EQ("Success", ec.message());
920- wait_for_update();
921+ EXPECT_TRUE(wait_for_update());
922
923 // Now check that we have 4 scopes registered
924 list = r->list();
925@@ -184,7 +257,7 @@
926 std::cout << "Move testscopeC back into the other_scopes folder" << std::endl;
927 filesystem::rename(TEST_RUNTIME_PATH "/scopes/testscopeC", TEST_RUNTIME_PATH "/other_scopes/testscopeC", ec);
928 ASSERT_EQ("Success", ec.message());
929- wait_for_update();
930+ EXPECT_TRUE(wait_for_update());
931
932 // Now check that we have 3 scopes registered again
933 list = r->list();
934@@ -198,7 +271,7 @@
935 std::cout << "Remove symlink to testscopeD from the scopes folder" << std::endl;
936 filesystem::remove(TEST_RUNTIME_PATH "/scopes/testscopeD", ec);
937 ASSERT_EQ("Success", ec.message());
938- wait_for_update();
939+ EXPECT_TRUE(wait_for_update());
940
941 // Now check that we are back to having 2 scopes registered
942 list = r->list();
943@@ -212,6 +285,7 @@
944 std::cout << "Make a folder in scopes named \"testfolder\"" << std::endl;
945 filesystem::create_directory(TEST_RUNTIME_PATH "/scopes/testfolder", ec);
946 ASSERT_EQ("Success", ec.message());
947+ EXPECT_FALSE(wait_for_update());
948
949 // Check that no scopes were registered
950 list = r->list();
951@@ -225,7 +299,7 @@
952 std::cout << "Make a symlink to testscopeC.ini in testfolder" << std::endl;
953 filesystem::create_symlink(TEST_RUNTIME_PATH "/other_scopes/testscopeC/testscopeC.ini", TEST_RUNTIME_PATH "/scopes/testfolder/testscopeC.ini", ec);
954 ASSERT_EQ("Success", ec.message());
955- wait_for_update();
956+ EXPECT_TRUE(wait_for_update());
957
958 // Now check that we have 3 scopes registered
959 list = r->list();
960@@ -239,7 +313,7 @@
961 std::cout << "Remove testfolder" << std::endl;
962 filesystem::remove_all(TEST_RUNTIME_PATH "/scopes/testfolder", ec);
963 ASSERT_EQ("Success", ec.message());
964- wait_for_update();
965+ EXPECT_TRUE(wait_for_update());
966
967 // Now check that we are back to having 2 scopes registered
968 list = r->list();
969
970=== modified file 'test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp'
971--- test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp 2014-05-20 04:20:46 +0000
972+++ test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp 2014-06-03 08:58:50 +0000
973@@ -167,16 +167,16 @@
974
975 // Create a few subscribers
976 auto subscriber1 = mw.create_subscriber("testpublisher", "testtopic1");
977- subscriber1->set_message_callback(std::bind(&SubMsgReceiver::receive1, &message_receiver, _1));
978+ subscriber1->message_received().connect(std::bind(&SubMsgReceiver::receive1, &message_receiver, _1));
979
980 auto subscriber2 = mw.create_subscriber("testpublisher", "testtopic2");
981- subscriber2->set_message_callback(std::bind(&SubMsgReceiver::receive2, &message_receiver, _1));
982+ subscriber2->message_received().connect(std::bind(&SubMsgReceiver::receive2, &message_receiver, _1));
983
984 auto subscriber3 = mw.create_subscriber("testpublisher", "");
985- subscriber3->set_message_callback(std::bind(&SubMsgReceiver::receive3, &message_receiver, _1));
986+ subscriber3->message_received().connect(std::bind(&SubMsgReceiver::receive3, &message_receiver, _1));
987
988 auto subscriber4 = mw.create_subscriber("testpublisher2", "testtopic4");
989- subscriber4->set_message_callback(std::bind(&SubMsgReceiver::receive4, &message_receiver, _1));
990+ subscriber4->message_received().connect(std::bind(&SubMsgReceiver::receive4, &message_receiver, _1));
991
992 // Give the subscribers some time to connect
993 std::this_thread::sleep_for(std::chrono::milliseconds(500));

Subscribers

People subscribed via source and target branches

to all changes: