Skip to content

Commit ae069f8

Browse files
release lock before calling customer code for config changes(CppMicroServices#1012) (CppMicroServices#1172)
Signed-off-by: Toby Cormack <tcormack@mathworks.com> Co-authored-by: tcormackMW <113473781+tcormackMW@users.noreply.github.com>
1 parent be0f1c8 commit ae069f8

2 files changed

Lines changed: 31 additions & 16 deletions

File tree

compendium/DeclarativeServices/src/manager/ConfigurationNotifier.cpp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

compendium/DeclarativeServices/src/manager/ConfigurationNotifier.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ namespace cppmicroservices
119119

120120
std::shared_ptr<cppmicroservices::logservice::LogService> logger;
121121
std::shared_ptr<ComponentFactoryImpl> componentFactory;
122+
std::mutex notificationOrderingLock;
122123
};
123124

124125
} // namespace scrimpl

0 commit comments

Comments
 (0)