@@ -46,13 +46,13 @@ namespace cppmicroservices
4646 , logger(logger)
4747 , componentFactory(std::make_shared<ComponentFactoryImpl>(context, logger, asyncWorkSvc, extensionReg))
4848
49- {
49+ {
5050 if (!context || !(this ->logger ) || !asyncWorkSvc || !extensionReg || !componentFactory)
5151 {
5252 throw std::invalid_argument (" ConfigurationNotifier Constructor "
5353 " provided with invalid arguments" );
5454 }
55- }
55+ }
5656
5757 cppmicroservices::ListenerTokenId
5858 ConfigurationNotifier::RegisterListener (std::string const & pid,
@@ -112,7 +112,8 @@ namespace cppmicroservices
112112 }
113113 }
114114 bool
115- ConfigurationNotifier::AnyListenersForPid (std::string const & pid, cppmicroservices::AnyMap const & properties) noexcept
115+ ConfigurationNotifier::AnyListenersForPid (std::string const & pid,
116+ cppmicroservices::AnyMap const & properties) noexcept
116117 {
117118 std::string factoryName;
118119 std::vector<std::shared_ptr<ComponentConfigurationImpl>> mgrs;
@@ -179,30 +180,43 @@ namespace cppmicroservices
179180 return true ;
180181 }
181182
182-
183183 void
184184 ConfigurationNotifier::NotifyAllListeners (std::string const & pid,
185185 cppmicroservices::service::cm::ConfigurationEventType type,
186186 std::shared_ptr<cppmicroservices::AnyMap> properties)
187187 {
188+ // lock held throughout to guarantee ordering for calls to this function
189+ std::lock_guard<std::mutex> l (notificationOrderingLock);
188190 ConfigChangeNotification notification
189191 = ConfigChangeNotification (pid, std::move (properties), std::move (type));
190-
191- auto listenersMapHandle = listenersMap.lock ();
192- auto iter = listenersMapHandle->find (pid);
193- if (iter != listenersMapHandle->end ())
192+ std::vector<Listener> callbacks;
194193 {
195- for (auto const & configListenerPtr : *(iter->second ))
194+ auto listenersMapHandle = listenersMap.lock ();
195+ auto iter = listenersMapHandle->find (pid);
196+ callbacks.reserve ((iter->second )->size ());
197+
198+ if (iter != listenersMapHandle->end ())
196199 {
197- configListenerPtr.second .notify (notification);
200+
201+ for (auto const & configListenerPtr : *(iter->second ))
202+ {
203+ // deep copy to get actual objects as opposed to shared_ptr to mutable map
204+ callbacks.emplace_back (configListenerPtr.second );
205+ }
206+ }
207+ else
208+ {
209+ return ;
198210 }
199211 }
200- else
212+ for ( auto const & listener : callbacks)
201213 {
202- return ;
214+ listener. notify (notification) ;
203215 }
204216 }
205- std::shared_ptr<ComponentFactoryImpl> ConfigurationNotifier::GetComponentFactory () {
217+ std::shared_ptr<ComponentFactoryImpl>
218+ ConfigurationNotifier::GetComponentFactory ()
219+ {
206220 return componentFactory;
207221 }
208222 void
@@ -222,9 +236,9 @@ namespace cppmicroservices
222236 {
223237 // This reference has a dynamic target
224238 logger->Log (cppmicroservices::logservice::SeverityLevel::LOG_ERROR,
225- " Properties for component " + metadata->name + " contains a dynamic target for interface "
226- + ref. interfaceName + " target= " + ref.target
227- + " Dynamic targets are only valid for factory components" );
239+ " Properties for component " + metadata->name
240+ + " contains a dynamic target for interface " + ref.interfaceName + " target= "
241+ + ref. target + " Dynamic targets are only valid for factory components" );
228242 }
229243 }
230244 }
0 commit comments