Skip to content

Commit e2176f7

Browse files
committed
update thread safe concept implementation
1 parent ee2fb54 commit e2176f7

File tree

1 file changed

+113
-95
lines changed

1 file changed

+113
-95
lines changed

Include/SevenBit/DI/ServiceProvider.hpp

Lines changed: 113 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,14 @@ namespace sb::di
9797
*/
9898
template <class TService> TService *tryGetService()
9999
{
100-
auto _ = tryUniqueLock();
101-
if (const auto instancePtr = getInstanceProvider().tryGetInstance(typeid(TService));
102-
instancePtr && *instancePtr)
103-
{
104-
return instancePtr->getAs<TService>();
105-
}
106-
return nullptr;
100+
return safeAction([&] -> TService * {
101+
if (const auto instancePtr = getInstanceProvider().tryGetInstance(typeid(TService));
102+
instancePtr && *instancePtr)
103+
{
104+
return instancePtr->getAs<TService>();
105+
}
106+
return nullptr;
107+
});
107108
}
108109

109110
/**
@@ -120,13 +121,14 @@ namespace sb::di
120121
*/
121122
template <class TService> TService *tryGetKeyedService(const std::string_view serviceKey)
122123
{
123-
auto _ = tryUniqueLock();
124-
if (const auto instancePtr = getInstanceProvider().tryGetKeyedInstance(typeid(TService), serviceKey);
125-
instancePtr && *instancePtr)
126-
{
127-
return instancePtr->getAs<TService>();
128-
}
129-
return nullptr;
124+
return safeAction([&] -> TService * {
125+
if (const auto instancePtr = getInstanceProvider().tryGetKeyedInstance(typeid(TService), serviceKey);
126+
instancePtr && *instancePtr)
127+
{
128+
return instancePtr->getAs<TService>();
129+
}
130+
return nullptr;
131+
});
130132
}
131133

132134
/**
@@ -143,10 +145,11 @@ namespace sb::di
143145
*/
144146
template <class TService> TService &getService()
145147
{
146-
auto _ = tryUniqueLock();
147-
auto &instance = getInstanceProvider().getInstance(typeid(TService));
148-
details::RequireInstance::valid(instance);
149-
return *instance.getAs<TService>();
148+
return *safeAction([&] -> TService * {
149+
auto &instance = getInstanceProvider().getInstance(typeid(TService));
150+
details::RequireInstance::valid(instance);
151+
return instance.getAs<TService>();
152+
});
150153
}
151154

152155
/**
@@ -164,10 +167,11 @@ namespace sb::di
164167
*/
165168
template <class TService> TService &getKeyedService(const std::string_view serviceKey)
166169
{
167-
auto _ = tryUniqueLock();
168-
auto &instance = getInstanceProvider().getKeyedInstance(typeid(TService), serviceKey);
169-
details::RequireInstance::valid(instance);
170-
return *instance.getAs<TService>();
170+
return *safeAction([&] -> TService * {
171+
auto &instance = getInstanceProvider().getKeyedInstance(typeid(TService), serviceKey);
172+
details::RequireInstance::valid(instance);
173+
return instance.getAs<TService>();
174+
});
171175
}
172176

173177
/**
@@ -186,15 +190,16 @@ namespace sb::di
186190
*/
187191
template <class TService> std::vector<TService *> getServices()
188192
{
189-
auto _ = tryUniqueLock();
190-
if (auto instancesPtr = getInstanceProvider().tryGetInstances(typeid(TService)))
191-
{
192-
return instancesPtr->map([](const ServiceInstance &instance) {
193-
details::RequireInstance::valid(instance);
194-
return instance.getAs<TService>();
195-
});
196-
}
197-
return {};
193+
return safeAction([&] -> std::vector<TService *> {
194+
if (auto instancesPtr = getInstanceProvider().tryGetInstances(typeid(TService)))
195+
{
196+
return instancesPtr->map([](const ServiceInstance &instance) {
197+
details::RequireInstance::valid(instance);
198+
return instance.getAs<TService>();
199+
});
200+
}
201+
return {};
202+
});
198203
}
199204

200205
/**
@@ -214,15 +219,16 @@ namespace sb::di
214219
*/
215220
template <class TService> std::vector<TService *> getKeyedServices(const std::string_view serviceKey)
216221
{
217-
auto _ = tryUniqueLock();
218-
if (auto instancesPtr = getInstanceProvider().tryGetKeyedInstances(typeid(TService), serviceKey))
219-
{
220-
return instancesPtr->map([](const ServiceInstance &instance) {
221-
details::RequireInstance::valid(instance);
222-
return instance.getAs<TService>();
223-
});
224-
}
225-
return {};
222+
return safeAction([&] -> std::vector<TService *> {
223+
if (auto instancesPtr = getInstanceProvider().tryGetKeyedInstances(typeid(TService), serviceKey))
224+
{
225+
return instancesPtr->map([](const ServiceInstance &instance) {
226+
details::RequireInstance::valid(instance);
227+
return instance.getAs<TService>();
228+
});
229+
}
230+
return {};
231+
});
226232
}
227233

228234
/**
@@ -238,12 +244,13 @@ namespace sb::di
238244
*/
239245
template <class TService> std::unique_ptr<TService> tryCreateService()
240246
{
241-
auto _ = tryUniqueLock();
242-
if (auto instance = getInstanceProvider().tryCreateInstance(typeid(TService)))
243-
{
244-
return instance.moveOutAsUniquePtr<TService>();
245-
}
246-
return nullptr;
247+
return safeAction([&] -> std::unique_ptr<TService> {
248+
if (auto instance = getInstanceProvider().tryCreateInstance(typeid(TService)))
249+
{
250+
return instance.moveOutAsUniquePtr<TService>();
251+
}
252+
return nullptr;
253+
});
247254
}
248255

249256
/**
@@ -260,12 +267,13 @@ namespace sb::di
260267
*/
261268
template <class TService> std::unique_ptr<TService> tryCreateKeyedService(const std::string_view serviceKey)
262269
{
263-
auto _ = tryUniqueLock();
264-
if (auto instance = getInstanceProvider().tryCreateKeyedInstance(typeid(TService), serviceKey))
265-
{
266-
return instance.moveOutAsUniquePtr<TService>();
267-
}
268-
return nullptr;
270+
return safeAction([&] -> std::unique_ptr<TService> {
271+
if (auto instance = getInstanceProvider().tryCreateKeyedInstance(typeid(TService), serviceKey))
272+
{
273+
return instance.moveOutAsUniquePtr<TService>();
274+
}
275+
return nullptr;
276+
});
269277
}
270278

271279
/**
@@ -282,10 +290,11 @@ namespace sb::di
282290
*/
283291
template <class TService> std::unique_ptr<TService> createService()
284292
{
285-
auto _ = tryUniqueLock();
286-
auto instance = getInstanceProvider().createInstance(typeid(TService));
287-
details::RequireInstance::valid(instance);
288-
return instance.moveOutAsUniquePtr<TService>();
293+
return safeAction([&] -> std::unique_ptr<TService> {
294+
auto instance = getInstanceProvider().createInstance(typeid(TService));
295+
details::RequireInstance::valid(instance);
296+
return instance.moveOutAsUniquePtr<TService>();
297+
});
289298
}
290299

291300
/**
@@ -303,10 +312,11 @@ namespace sb::di
303312
*/
304313
template <class TService> std::unique_ptr<TService> createKeyedService(const std::string_view serviceKey)
305314
{
306-
auto _ = tryUniqueLock();
307-
auto instance = getInstanceProvider().createKeyedInstance(typeid(TService), serviceKey);
308-
details::RequireInstance::valid(instance);
309-
return instance.moveOutAsUniquePtr<TService>();
315+
return safeAction([&] -> std::unique_ptr<TService> {
316+
auto instance = getInstanceProvider().createKeyedInstance(typeid(TService), serviceKey);
317+
details::RequireInstance::valid(instance);
318+
return instance.moveOutAsUniquePtr<TService>();
319+
});
310320
}
311321

312322
/**
@@ -323,17 +333,18 @@ namespace sb::di
323333
*/
324334
template <class TService> TService createServiceInPlace()
325335
{
326-
auto _ = tryUniqueLock();
327-
auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService));
328-
details::RequireInstance::valid(instance);
329-
if constexpr (std::is_move_constructible_v<TService>)
330-
{
331-
return instance.moveOutAs<TService>();
332-
}
333-
else
334-
{
335-
return instance.copyAs<TService>();
336-
}
336+
return safeAction([&] -> TService {
337+
auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService));
338+
details::RequireInstance::valid(instance);
339+
if constexpr (std::is_move_constructible_v<TService>)
340+
{
341+
return instance.moveOutAs<TService>();
342+
}
343+
else
344+
{
345+
return instance.copyAs<TService>();
346+
}
347+
});
337348
}
338349

339350
/**
@@ -351,17 +362,18 @@ namespace sb::di
351362
*/
352363
template <class TService> TService createKeyedServiceInPlace(const std::string_view serviceKey)
353364
{
354-
auto _ = tryUniqueLock();
355-
auto instance = getInstanceProvider().createKeyedInstanceInPlace(typeid(TService), serviceKey);
356-
details::RequireInstance::valid(instance);
357-
if constexpr (std::is_move_constructible_v<TService>)
358-
{
359-
return instance.moveOutAs<TService>();
360-
}
361-
else
362-
{
363-
return instance.copyAs<TService>();
364-
}
365+
return safeAction([&] -> TService {
366+
auto instance = getInstanceProvider().createKeyedInstanceInPlace(typeid(TService), serviceKey);
367+
details::RequireInstance::valid(instance);
368+
if constexpr (std::is_move_constructible_v<TService>)
369+
{
370+
return instance.moveOutAs<TService>();
371+
}
372+
else
373+
{
374+
return instance.copyAs<TService>();
375+
}
376+
});
365377
}
366378

367379
/**
@@ -380,11 +392,12 @@ namespace sb::di
380392
*/
381393
template <class TService> std::vector<std::unique_ptr<TService>> createServices()
382394
{
383-
auto _ = tryUniqueLock();
384-
auto instances = getInstanceProvider().tryCreateInstances(typeid(TService));
385-
return instances.map([&](ServiceInstance &instance) {
386-
details::RequireInstance::valid(instance);
387-
return instance.moveOutAsUniquePtr<TService>();
395+
return safeAction([&] -> std::vector<std::unique_ptr<TService>> {
396+
auto instances = getInstanceProvider().tryCreateInstances(typeid(TService));
397+
return instances.map([&](ServiceInstance &instance) {
398+
details::RequireInstance::valid(instance);
399+
return instance.moveOutAsUniquePtr<TService>();
400+
});
388401
});
389402
}
390403

@@ -406,19 +419,24 @@ namespace sb::di
406419
template <class TService>
407420
std::vector<std::unique_ptr<TService>> createKeyedServices(const std::string_view serviceKey)
408421
{
409-
auto _ = tryUniqueLock();
410-
auto instances = getInstanceProvider().tryCreateKeyedInstances(typeid(TService), serviceKey);
411-
return instances.map([&](ServiceInstance &instance) {
412-
details::RequireInstance::valid(instance);
413-
return instance.moveOutAsUniquePtr<TService>();
422+
return safeAction([&] -> std::vector<std::unique_ptr<TService>> {
423+
auto instances = getInstanceProvider().tryCreateKeyedInstances(typeid(TService), serviceKey);
424+
return instances.map([&](ServiceInstance &instance) {
425+
details::RequireInstance::valid(instance);
426+
return instance.moveOutAsUniquePtr<TService>();
427+
});
414428
});
415429
}
416430

417431
private:
418-
std::optional<std::unique_lock<std::recursive_mutex>> tryUniqueLock()
432+
template <class TAction> auto safeAction(TAction action)
419433
{
420-
const auto mutexPtr = getInstanceProvider().tryGetSyncMutex();
421-
return mutexPtr ? std::make_optional(std::unique_lock{*mutexPtr}) : std::nullopt;
434+
if (const auto mutexPtr = getInstanceProvider().tryGetSyncMutex())
435+
{
436+
std::lock_guard lock{*mutexPtr};
437+
return action();
438+
}
439+
return action();
422440
}
423441
};
424442
} // namespace sb::di

0 commit comments

Comments
 (0)