From 4a8c3a21207f540bf306ae561035796e61358853 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Thu, 2 May 2024 18:32:06 +0200 Subject: [PATCH 01/12] first thread safe concept implementation --- .../Core/Impl/ServiceInstanceProvider.hpp | 2 +- .../SevenBit/DI/Impl/ServiceCollection.hpp | 3 +- Include/SevenBit/DI/ServiceProvider.hpp | 28 ++++++++++++++++++- .../SevenBit/DI/ServiceProviderOptions.hpp | 2 ++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 9d39b3c..365eb3f 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -27,7 +27,7 @@ namespace sb::di::details INLINE IServiceInstanceProvider::Ptr ServiceInstanceProvider::createScope() const { - return std::make_unique(_root, _options); + return std::make_unique(_root, getOptions()); } INLINE const ServiceInstance &ServiceInstanceProvider::getInstance(const ServiceId &id) diff --git a/Include/SevenBit/DI/Impl/ServiceCollection.hpp b/Include/SevenBit/DI/Impl/ServiceCollection.hpp index 45f60d2..573d57a 100644 --- a/Include/SevenBit/DI/Impl/ServiceCollection.hpp +++ b/Include/SevenBit/DI/Impl/ServiceCollection.hpp @@ -11,7 +11,8 @@ namespace sb::di { INLINE ServiceProvider ServiceCollection::buildServiceProvider(ServiceProviderOptions options) { - return ServiceProvider{std::make_unique(begin(), end(), options)}; + return ServiceProvider{std::make_unique(begin(), end(), options), + options.threadSafe}; } INLINE ServiceProvider::Ptr ServiceCollection::buildServiceProviderAsPtr(ServiceProviderOptions options) diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index 83c8345..ff03ea7 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -15,6 +16,7 @@ namespace sb::di class ServiceProvider { IServiceInstanceProvider::Ptr _instanceProvider; + std::unique_ptr _mutex; public: using Ptr = std::unique_ptr; @@ -22,9 +24,13 @@ namespace sb::di /** * @brief Constructs service provider with specified instance provider */ - explicit ServiceProvider(IServiceInstanceProvider::Ptr instanceProvider) + explicit ServiceProvider(IServiceInstanceProvider::Ptr instanceProvider, const bool threadSafe = false) : _instanceProvider(std::move(instanceProvider)) { + if (threadSafe) + { + _mutex = std::make_unique(); + } details::Require::notNull(_instanceProvider); getInstanceProvider().init(*this); } @@ -96,6 +102,7 @@ namespace sb::di */ template TService *tryGetService() { + auto _ = tryUniqueLock(); if (const auto instancePtr = getInstanceProvider().tryGetInstance(typeid(TService)); instancePtr && *instancePtr) { @@ -118,6 +125,7 @@ namespace sb::di */ template TService *tryGetKeyedService(const std::string_view serviceKey) { + auto _ = tryUniqueLock(); if (const auto instancePtr = getInstanceProvider().tryGetKeyedInstance(typeid(TService), serviceKey); instancePtr && *instancePtr) { @@ -140,6 +148,7 @@ namespace sb::di */ template TService &getService() { + auto _ = tryUniqueLock(); auto &instance = getInstanceProvider().getInstance(typeid(TService)); details::RequireInstance::valid(instance); return *instance.getAs(); @@ -160,6 +169,7 @@ namespace sb::di */ template TService &getKeyedService(const std::string_view serviceKey) { + auto _ = tryUniqueLock(); auto &instance = getInstanceProvider().getKeyedInstance(typeid(TService), serviceKey); details::RequireInstance::valid(instance); return *instance.getAs(); @@ -181,6 +191,7 @@ namespace sb::di */ template std::vector getServices() { + auto _ = tryUniqueLock(); if (auto instancesPtr = getInstanceProvider().tryGetInstances(typeid(TService))) { return instancesPtr->map([](const ServiceInstance &instance) { @@ -208,6 +219,7 @@ namespace sb::di */ template std::vector getKeyedServices(const std::string_view serviceKey) { + auto _ = tryUniqueLock(); if (auto instancesPtr = getInstanceProvider().tryGetKeyedInstances(typeid(TService), serviceKey)) { return instancesPtr->map([](const ServiceInstance &instance) { @@ -231,6 +243,7 @@ namespace sb::di */ template std::unique_ptr tryCreateService() { + auto _ = tryUniqueLock(); if (auto instance = getInstanceProvider().tryCreateInstance(typeid(TService))) { return instance.moveOutAsUniquePtr(); @@ -252,6 +265,7 @@ namespace sb::di */ template std::unique_ptr tryCreateKeyedService(const std::string_view serviceKey) { + auto _ = tryUniqueLock(); if (auto instance = getInstanceProvider().tryCreateKeyedInstance(typeid(TService), serviceKey)) { return instance.moveOutAsUniquePtr(); @@ -273,6 +287,7 @@ namespace sb::di */ template std::unique_ptr createService() { + auto _ = tryUniqueLock(); auto instance = getInstanceProvider().createInstance(typeid(TService)); details::RequireInstance::valid(instance); return instance.moveOutAsUniquePtr(); @@ -293,6 +308,7 @@ namespace sb::di */ template std::unique_ptr createKeyedService(const std::string_view serviceKey) { + auto _ = tryUniqueLock(); auto instance = getInstanceProvider().createKeyedInstance(typeid(TService), serviceKey); details::RequireInstance::valid(instance); return instance.moveOutAsUniquePtr(); @@ -312,6 +328,7 @@ namespace sb::di */ template TService createServiceInPlace() { + auto _ = tryUniqueLock(); auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService)); details::RequireInstance::valid(instance); if constexpr (std::is_move_constructible_v) @@ -339,6 +356,7 @@ namespace sb::di */ template TService createKeyedServiceInPlace(const std::string_view serviceKey) { + auto _ = tryUniqueLock(); auto instance = getInstanceProvider().createKeyedInstanceInPlace(typeid(TService), serviceKey); details::RequireInstance::valid(instance); if constexpr (std::is_move_constructible_v) @@ -367,6 +385,7 @@ namespace sb::di */ template std::vector> createServices() { + auto _ = tryUniqueLock(); auto instances = getInstanceProvider().tryCreateInstances(typeid(TService)); return instances.map([&](ServiceInstance &instance) { details::RequireInstance::valid(instance); @@ -392,11 +411,18 @@ namespace sb::di template std::vector> createKeyedServices(const std::string_view serviceKey) { + auto _ = tryUniqueLock(); auto instances = getInstanceProvider().tryCreateKeyedInstances(typeid(TService), serviceKey); return instances.map([&](ServiceInstance &instance) { details::RequireInstance::valid(instance); return instance.moveOutAsUniquePtr(); }); } + + private: + std::optional> tryUniqueLock() + { + return _mutex ? std::make_optional(std::unique_lock{*_mutex}) : std::nullopt; + } }; } // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceProviderOptions.hpp b/Include/SevenBit/DI/ServiceProviderOptions.hpp index c4265d2..496ea7a 100644 --- a/Include/SevenBit/DI/ServiceProviderOptions.hpp +++ b/Include/SevenBit/DI/ServiceProviderOptions.hpp @@ -33,5 +33,7 @@ namespace sb::di * @details If set to true provider will search for service in singleton container first then in scoped */ bool searchInSigletonsFirst = true; + + bool threadSafe = false; }; } // namespace sb::di From 7caec7d73779bd56e0f175ed996632f18b0741f7 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Thu, 2 May 2024 19:01:20 +0200 Subject: [PATCH 02/12] add thread safe concept implementation --- .../Details/Core/IServiceInstanceProviderRoot.hpp | 4 ++++ .../DI/Details/Core/ServiceInstanceProvider.hpp | 2 ++ .../DI/Details/Core/ServiceInstanceProviderRoot.hpp | 7 +++++++ Include/SevenBit/DI/IServiceInstanceProvider.hpp | 3 +++ Include/SevenBit/DI/Impl/ServiceCollection.hpp | 3 +-- Include/SevenBit/DI/ServiceProvider.hpp | 13 ++++++------- Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp | 1 + 7 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp index 2005116..67aab32 100644 --- a/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp" @@ -16,6 +18,8 @@ namespace sb::di::details virtual ServiceInstancesCreator &getRootCreator() = 0; + virtual std::recursive_mutex *tryGetSyncMutex() = 0; + virtual ~IServiceInstanceProviderRoot() = default; }; } // namespace sb::di::details diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 04ace73..6a3a840 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -39,6 +39,8 @@ namespace sb::di::details [[nodiscard]] IServiceInstanceProvider::Ptr createScope() const override; + std::recursive_mutex *tryGetSyncMutex() override { return _root.tryGetSyncMutex(); } + const ServiceInstance &getInstance(const TypeId serviceTypeId) override { return getInstance(ServiceId{serviceTypeId}); diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp index d51ac52..594311d 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp @@ -13,6 +13,7 @@ namespace sb::di::details { ServiceDescriptorsMap _descriptorsMap; ServiceInstancesMap _singletons; + std::unique_ptr _mutex; public: using Ptr = std::unique_ptr; @@ -26,6 +27,10 @@ namespace sb::di::details _descriptorsMap(begin, end, options.checkServiceGlobalUniqueness), _singletons(options.strongDestructionOrder) { + if (options.threadSafe) + { + _mutex = std::make_unique(); + } _descriptorsMap.seal(); } @@ -37,6 +42,8 @@ namespace sb::di::details ServiceInstancesCreator &getRootCreator() override { return getCreator(); } + std::recursive_mutex *tryGetSyncMutex() override { return _mutex.get(); } + private: void prebuildSingletons(); }; diff --git a/Include/SevenBit/DI/IServiceInstanceProvider.hpp b/Include/SevenBit/DI/IServiceInstanceProvider.hpp index d9d5015..e4f7e71 100644 --- a/Include/SevenBit/DI/IServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/IServiceInstanceProvider.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -29,6 +30,8 @@ namespace sb::di */ [[nodiscard]] virtual Ptr createScope() const = 0; + virtual std::recursive_mutex *tryGetSyncMutex() = 0; + /** * @brief Returns service instance reference, might throw exception * @details If service was not registered or was registered as transient, method throws exception diff --git a/Include/SevenBit/DI/Impl/ServiceCollection.hpp b/Include/SevenBit/DI/Impl/ServiceCollection.hpp index 573d57a..45f60d2 100644 --- a/Include/SevenBit/DI/Impl/ServiceCollection.hpp +++ b/Include/SevenBit/DI/Impl/ServiceCollection.hpp @@ -11,8 +11,7 @@ namespace sb::di { INLINE ServiceProvider ServiceCollection::buildServiceProvider(ServiceProviderOptions options) { - return ServiceProvider{std::make_unique(begin(), end(), options), - options.threadSafe}; + return ServiceProvider{std::make_unique(begin(), end(), options)}; } INLINE ServiceProvider::Ptr ServiceCollection::buildServiceProviderAsPtr(ServiceProviderOptions options) diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index ff03ea7..7edcef4 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -16,7 +16,6 @@ namespace sb::di class ServiceProvider { IServiceInstanceProvider::Ptr _instanceProvider; - std::unique_ptr _mutex; public: using Ptr = std::unique_ptr; @@ -24,13 +23,9 @@ namespace sb::di /** * @brief Constructs service provider with specified instance provider */ - explicit ServiceProvider(IServiceInstanceProvider::Ptr instanceProvider, const bool threadSafe = false) + explicit ServiceProvider(IServiceInstanceProvider::Ptr instanceProvider) : _instanceProvider(std::move(instanceProvider)) { - if (threadSafe) - { - _mutex = std::make_unique(); - } details::Require::notNull(_instanceProvider); getInstanceProvider().init(*this); } @@ -422,7 +417,11 @@ namespace sb::di private: std::optional> tryUniqueLock() { - return _mutex ? std::make_optional(std::unique_lock{*_mutex}) : std::nullopt; + if (const auto mutex = getInstanceProvider().tryGetSyncMutex()) + { + return std::unique_lock{*mutex}; + } + return std::nullopt; } }; } // namespace sb::di diff --git a/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp b/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp index dc315cf..4fa46f9 100644 --- a/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp +++ b/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp @@ -7,6 +7,7 @@ struct ServiceInstanceProviderMock : public sb::di::IServiceInstanceProvider { MOCK_METHOD((std::unique_ptr), createScope, (), (const override)); + MOCK_METHOD((std::recursive_mutex *), tryGetSyncMutex, (), (override)); MOCK_METHOD((void), init, (sb::di::ServiceProvider &), (override)); MOCK_METHOD((const sb::di::ServiceInstance *), tryGetInstance, (sb::di::TypeId serviceTypeId), (override)); MOCK_METHOD((const sb::di::ServiceInstance &), getInstance, (sb::di::TypeId serviceTypeId), (override)); From ee2fb54422745906fa63c108da96c5c2821065d9 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Thu, 2 May 2024 21:53:20 +0200 Subject: [PATCH 03/12] update thread safe concept implementation and update docs --- .../SevenBit/DI/IServiceInstanceProvider.hpp | 5 +++ Include/SevenBit/DI/ServiceCollection.hpp | 44 ++++++++++--------- Include/SevenBit/DI/ServiceProvider.hpp | 39 ++++++++-------- .../SevenBit/DI/ServiceProviderOptions.hpp | 4 ++ 4 files changed, 51 insertions(+), 41 deletions(-) diff --git a/Include/SevenBit/DI/IServiceInstanceProvider.hpp b/Include/SevenBit/DI/IServiceInstanceProvider.hpp index e4f7e71..2ea20cd 100644 --- a/Include/SevenBit/DI/IServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/IServiceInstanceProvider.hpp @@ -30,6 +30,11 @@ namespace sb::di */ [[nodiscard]] virtual Ptr createScope() const = 0; + /** + * @brief Get sync mutex + * @details Mutex can be used to synchronize service accesses between threads, can be null if synchronization is + * not needed + */ virtual std::recursive_mutex *tryGetSyncMutex() = 0; /** diff --git a/Include/SevenBit/DI/ServiceCollection.hpp b/Include/SevenBit/DI/ServiceCollection.hpp index 502f5b8..cfe4bc4 100644 --- a/Include/SevenBit/DI/ServiceCollection.hpp +++ b/Include/SevenBit/DI/ServiceCollection.hpp @@ -476,8 +476,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.add(ServiceLifeTimes::Scoped, "key"); - * ServiceCollection{}.add(ServiceLifeTimes::Transient, "key"); + * ServiceCollection{}.addKeyed(ServiceLifeTimes::Scoped, "key"); + * ServiceCollection{}.addKeyed(ServiceLifeTimes::Transient, "key"); * @endcode */ template @@ -515,8 +515,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addSingleton("key"); - * ServiceCollection{}.addSingleton("key"); + * ServiceCollection{}.addKeyedSingleton("key"); + * ServiceCollection{}.addKeyedSingleton("key"); * @endcode */ template @@ -554,8 +554,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addScoped("key"); - * ServiceCollection{}.addScoped("key"); + * ServiceCollection{}.addKeyedScoped("key"); + * ServiceCollection{}.addKeyedScoped("key"); * @endcode */ template @@ -593,8 +593,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addTransient("key"); - * ServiceCollection{}.addTransient("key"); + * ServiceCollection{}.addKeyedTransient("key"); + * ServiceCollection{}.addKeyedTransient("key"); * @endcode */ template @@ -629,7 +629,7 @@ namespace sb::di * Example: * @code{.cpp} * TestClass test; - * ServiceCollection{}.addSingleton("key", &test); + * ServiceCollection{}.addKeyedSingleton("key", &test); * @endcode */ template ServiceCollection &addKeyedSingleton(std::string serviceKey, TService *service) @@ -667,7 +667,7 @@ namespace sb::di * Example: * @code{.cpp} * ImplementationClass implementation; - * ServiceCollection{}.addSingleton("key", &implementation); + * ServiceCollection{}.addKeyedSingleton("key", &implementation); * @endcode */ template @@ -710,7 +710,7 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.add(ServiceLifeTimes::Scoped, "key", + * ServiceCollection{}.addKeyed(ServiceLifeTimes::Scoped, "key", * []() { return std::make_unique(); }); * @endcode */ @@ -750,7 +750,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addSingleton("key", []() { return std::make_unique(); }); + * ServiceCollection{}.addKeyedSingleton("key", []() { return + * std::make_unique(); }); * @endcode */ template @@ -789,7 +790,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addScoped("key", []() { return std::make_unique(); }); + * ServiceCollection{}.addKeyedScoped("key", []() { return std::make_unique(); + * }); * @endcode */ template @@ -828,7 +830,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addTransient("key", []() { return std::make_unique(); }); + * ServiceCollection{}.addKeyedTransient("key", []() { return + * std::make_unique(); }); * @endcode */ template @@ -867,7 +870,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.add(ServiceLifeTimes::Transient, "key", []() { return std::make_unique(); }); + * ServiceCollection{}.addKeyed(ServiceLifeTimes::Transient, "key", []() { return std::make_unique(); + * }); * @endcode */ template @@ -904,7 +908,7 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addSingleton("key", []() { return std::make_unique(); }); + * ServiceCollection{}.addKeyedSingleton("key", []() { return std::make_unique(); }); * @endcode */ template ServiceCollection &addKeyedSingleton(std::string serviceKey, FactoryFcn factory) @@ -940,7 +944,7 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addScoped("key", []() { return std::make_unique(); }); + * ServiceCollection{}.addKeyedScoped("key", []() { return std::make_unique(); }); * @endcode */ template ServiceCollection &addKeyedScoped(std::string serviceKey, FactoryFcn factory) @@ -976,7 +980,7 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addTransient("key", []() { return std::make_unique(); }); + * ServiceCollection{}.addKeyedTransient("key", []() { return std::make_unique(); }); * @endcode */ template ServiceCollection &addKeyedTransient(std::string serviceKey, FactoryFcn factory) @@ -1026,7 +1030,7 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addAlias("aliasKey", "key"); + * ServiceCollection{}.addKeyedAlias("aliasKey", "key"); * @endcode */ template @@ -1045,7 +1049,7 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.addAlias("aliasKey"); + * ServiceCollection{}.addKeyedAlias("aliasKey"); * @endcode */ template ServiceCollection &addKeyedAlias(std::string serviceAliasKey) diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index 7edcef4..a78ff15 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -113,9 +113,9 @@ namespace sb::di * * Example: * @code{.cpp} - * auto provider = ServiceCollection{}.addScoped().buildServiceProvider(); + * auto provider = ServiceCollection{}.addKeyedScoped("key").buildServiceProvider(); * - * TestClass* service = provider.tryGetService(); + * TestClass* service = provider.tryGetKeyedService("key"); * @endcode */ template TService *tryGetKeyedService(const std::string_view serviceKey) @@ -157,9 +157,9 @@ namespace sb::di * * Example: * @code{.cpp} - * auto provider = ServiceCollection{}.addScoped().buildServiceProvider(); + * auto provider = ServiceCollection{}.addKeyedScoped("key").buildServiceProvider(); * - * TestClass& service = provider.getService(); + * TestClass& service = provider.getKeyedService("key"); * @endcode */ template TService &getKeyedService(const std::string_view serviceKey) @@ -205,11 +205,11 @@ namespace sb::di * Example: * @code{.cpp} * auto provider = ServiceCollection{} - * .addScoped() - * .addScoped() + * .addKeyedScoped("key") + * .addKeyedScoped("key") * .buildServiceProvider(); * - * std::vector services = provider.getServices(); + * std::vector services = provider.getKeyedServices("key"); * @endcode */ template std::vector getKeyedServices(const std::string_view serviceKey) @@ -253,9 +253,9 @@ namespace sb::di * * Example: * @code{.cpp} - * auto provider = ServiceCollection{}.addTransient().buildServiceProvider(); + * auto provider = ServiceCollection{}.addKeyedTransient("key").buildServiceProvider(); * - * std::unique_ptr service = provider.tryCreateService(); + * std::unique_ptr service = provider.tryCreateKeyedService("key"); * @endcode */ template std::unique_ptr tryCreateKeyedService(const std::string_view serviceKey) @@ -296,9 +296,9 @@ namespace sb::di * * Example: * @code{.cpp} - * auto provider = ServiceCollection{}.addTransient().buildServiceProvider(); + * auto provider = ServiceCollection{}.addKeyedTransient("key").buildServiceProvider(); * - * std::unique_ptr service = provider.createService(); + * std::unique_ptr service = provider.createKeyedService("key"); * @endcode */ template std::unique_ptr createKeyedService(const std::string_view serviceKey) @@ -344,9 +344,9 @@ namespace sb::di * * Example: * @code{.cpp} - * auto provider = ServiceCollection{}.addTransient().buildServiceProvider(); + * auto provider = ServiceCollection{}.addKeyedTransient("key").buildServiceProvider(); * - * TestClass service = provider.createServiceInPlace(); + * TestClass service = provider.createKeyedServiceInPlace("key"); * @endcode */ template TService createKeyedServiceInPlace(const std::string_view serviceKey) @@ -396,11 +396,11 @@ namespace sb::di * Example: * @code{.cpp} * auto provider = ServiceCollection{} - * .addTransient() - * .addTransient() + * .addKeyedTransient("key") + * .addKeyedTransient("key") * .buildServiceProvider(); * - * std::vector> services = provider.createServices(); + * std::vector> services = provider.createKeyedServices("key"); * @endcode */ template @@ -417,11 +417,8 @@ namespace sb::di private: std::optional> tryUniqueLock() { - if (const auto mutex = getInstanceProvider().tryGetSyncMutex()) - { - return std::unique_lock{*mutex}; - } - return std::nullopt; + const auto mutexPtr = getInstanceProvider().tryGetSyncMutex(); + return mutexPtr ? std::make_optional(std::unique_lock{*mutexPtr}) : std::nullopt; } }; } // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceProviderOptions.hpp b/Include/SevenBit/DI/ServiceProviderOptions.hpp index 496ea7a..8eea451 100644 --- a/Include/SevenBit/DI/ServiceProviderOptions.hpp +++ b/Include/SevenBit/DI/ServiceProviderOptions.hpp @@ -34,6 +34,10 @@ namespace sb::di */ bool searchInSigletonsFirst = true; + /** + * @brief Enables thread safe mode + * @details Provider will synchronize service accesses between threads + */ bool threadSafe = false; }; } // namespace sb::di From e2176f7dbc64271bfaccc4ccbd5720e2768c860c Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 4 May 2024 12:39:20 +0200 Subject: [PATCH 04/12] update thread safe concept implementation --- Include/SevenBit/DI/ServiceProvider.hpp | 208 +++++++++++++----------- 1 file changed, 113 insertions(+), 95 deletions(-) diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index a78ff15..f97f2eb 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -97,13 +97,14 @@ namespace sb::di */ template TService *tryGetService() { - auto _ = tryUniqueLock(); - if (const auto instancePtr = getInstanceProvider().tryGetInstance(typeid(TService)); - instancePtr && *instancePtr) - { - return instancePtr->getAs(); - } - return nullptr; + return safeAction([&] -> TService * { + if (const auto instancePtr = getInstanceProvider().tryGetInstance(typeid(TService)); + instancePtr && *instancePtr) + { + return instancePtr->getAs(); + } + return nullptr; + }); } /** @@ -120,13 +121,14 @@ namespace sb::di */ template TService *tryGetKeyedService(const std::string_view serviceKey) { - auto _ = tryUniqueLock(); - if (const auto instancePtr = getInstanceProvider().tryGetKeyedInstance(typeid(TService), serviceKey); - instancePtr && *instancePtr) - { - return instancePtr->getAs(); - } - return nullptr; + return safeAction([&] -> TService * { + if (const auto instancePtr = getInstanceProvider().tryGetKeyedInstance(typeid(TService), serviceKey); + instancePtr && *instancePtr) + { + return instancePtr->getAs(); + } + return nullptr; + }); } /** @@ -143,10 +145,11 @@ namespace sb::di */ template TService &getService() { - auto _ = tryUniqueLock(); - auto &instance = getInstanceProvider().getInstance(typeid(TService)); - details::RequireInstance::valid(instance); - return *instance.getAs(); + return *safeAction([&] -> TService * { + auto &instance = getInstanceProvider().getInstance(typeid(TService)); + details::RequireInstance::valid(instance); + return instance.getAs(); + }); } /** @@ -164,10 +167,11 @@ namespace sb::di */ template TService &getKeyedService(const std::string_view serviceKey) { - auto _ = tryUniqueLock(); - auto &instance = getInstanceProvider().getKeyedInstance(typeid(TService), serviceKey); - details::RequireInstance::valid(instance); - return *instance.getAs(); + return *safeAction([&] -> TService * { + auto &instance = getInstanceProvider().getKeyedInstance(typeid(TService), serviceKey); + details::RequireInstance::valid(instance); + return instance.getAs(); + }); } /** @@ -186,15 +190,16 @@ namespace sb::di */ template std::vector getServices() { - auto _ = tryUniqueLock(); - if (auto instancesPtr = getInstanceProvider().tryGetInstances(typeid(TService))) - { - return instancesPtr->map([](const ServiceInstance &instance) { - details::RequireInstance::valid(instance); - return instance.getAs(); - }); - } - return {}; + return safeAction([&] -> std::vector { + if (auto instancesPtr = getInstanceProvider().tryGetInstances(typeid(TService))) + { + return instancesPtr->map([](const ServiceInstance &instance) { + details::RequireInstance::valid(instance); + return instance.getAs(); + }); + } + return {}; + }); } /** @@ -214,15 +219,16 @@ namespace sb::di */ template std::vector getKeyedServices(const std::string_view serviceKey) { - auto _ = tryUniqueLock(); - if (auto instancesPtr = getInstanceProvider().tryGetKeyedInstances(typeid(TService), serviceKey)) - { - return instancesPtr->map([](const ServiceInstance &instance) { - details::RequireInstance::valid(instance); - return instance.getAs(); - }); - } - return {}; + return safeAction([&] -> std::vector { + if (auto instancesPtr = getInstanceProvider().tryGetKeyedInstances(typeid(TService), serviceKey)) + { + return instancesPtr->map([](const ServiceInstance &instance) { + details::RequireInstance::valid(instance); + return instance.getAs(); + }); + } + return {}; + }); } /** @@ -238,12 +244,13 @@ namespace sb::di */ template std::unique_ptr tryCreateService() { - auto _ = tryUniqueLock(); - if (auto instance = getInstanceProvider().tryCreateInstance(typeid(TService))) - { - return instance.moveOutAsUniquePtr(); - } - return nullptr; + return safeAction([&] -> std::unique_ptr { + if (auto instance = getInstanceProvider().tryCreateInstance(typeid(TService))) + { + return instance.moveOutAsUniquePtr(); + } + return nullptr; + }); } /** @@ -260,12 +267,13 @@ namespace sb::di */ template std::unique_ptr tryCreateKeyedService(const std::string_view serviceKey) { - auto _ = tryUniqueLock(); - if (auto instance = getInstanceProvider().tryCreateKeyedInstance(typeid(TService), serviceKey)) - { - return instance.moveOutAsUniquePtr(); - } - return nullptr; + return safeAction([&] -> std::unique_ptr { + if (auto instance = getInstanceProvider().tryCreateKeyedInstance(typeid(TService), serviceKey)) + { + return instance.moveOutAsUniquePtr(); + } + return nullptr; + }); } /** @@ -282,10 +290,11 @@ namespace sb::di */ template std::unique_ptr createService() { - auto _ = tryUniqueLock(); - auto instance = getInstanceProvider().createInstance(typeid(TService)); - details::RequireInstance::valid(instance); - return instance.moveOutAsUniquePtr(); + return safeAction([&] -> std::unique_ptr { + auto instance = getInstanceProvider().createInstance(typeid(TService)); + details::RequireInstance::valid(instance); + return instance.moveOutAsUniquePtr(); + }); } /** @@ -303,10 +312,11 @@ namespace sb::di */ template std::unique_ptr createKeyedService(const std::string_view serviceKey) { - auto _ = tryUniqueLock(); - auto instance = getInstanceProvider().createKeyedInstance(typeid(TService), serviceKey); - details::RequireInstance::valid(instance); - return instance.moveOutAsUniquePtr(); + return safeAction([&] -> std::unique_ptr { + auto instance = getInstanceProvider().createKeyedInstance(typeid(TService), serviceKey); + details::RequireInstance::valid(instance); + return instance.moveOutAsUniquePtr(); + }); } /** @@ -323,17 +333,18 @@ namespace sb::di */ template TService createServiceInPlace() { - auto _ = tryUniqueLock(); - auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService)); - details::RequireInstance::valid(instance); - if constexpr (std::is_move_constructible_v) - { - return instance.moveOutAs(); - } - else - { - return instance.copyAs(); - } + return safeAction([&] -> TService { + auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService)); + details::RequireInstance::valid(instance); + if constexpr (std::is_move_constructible_v) + { + return instance.moveOutAs(); + } + else + { + return instance.copyAs(); + } + }); } /** @@ -351,17 +362,18 @@ namespace sb::di */ template TService createKeyedServiceInPlace(const std::string_view serviceKey) { - auto _ = tryUniqueLock(); - auto instance = getInstanceProvider().createKeyedInstanceInPlace(typeid(TService), serviceKey); - details::RequireInstance::valid(instance); - if constexpr (std::is_move_constructible_v) - { - return instance.moveOutAs(); - } - else - { - return instance.copyAs(); - } + return safeAction([&] -> TService { + auto instance = getInstanceProvider().createKeyedInstanceInPlace(typeid(TService), serviceKey); + details::RequireInstance::valid(instance); + if constexpr (std::is_move_constructible_v) + { + return instance.moveOutAs(); + } + else + { + return instance.copyAs(); + } + }); } /** @@ -380,11 +392,12 @@ namespace sb::di */ template std::vector> createServices() { - auto _ = tryUniqueLock(); - auto instances = getInstanceProvider().tryCreateInstances(typeid(TService)); - return instances.map([&](ServiceInstance &instance) { - details::RequireInstance::valid(instance); - return instance.moveOutAsUniquePtr(); + return safeAction([&] -> std::vector> { + auto instances = getInstanceProvider().tryCreateInstances(typeid(TService)); + return instances.map([&](ServiceInstance &instance) { + details::RequireInstance::valid(instance); + return instance.moveOutAsUniquePtr(); + }); }); } @@ -406,19 +419,24 @@ namespace sb::di template std::vector> createKeyedServices(const std::string_view serviceKey) { - auto _ = tryUniqueLock(); - auto instances = getInstanceProvider().tryCreateKeyedInstances(typeid(TService), serviceKey); - return instances.map([&](ServiceInstance &instance) { - details::RequireInstance::valid(instance); - return instance.moveOutAsUniquePtr(); + return safeAction([&] -> std::vector> { + auto instances = getInstanceProvider().tryCreateKeyedInstances(typeid(TService), serviceKey); + return instances.map([&](ServiceInstance &instance) { + details::RequireInstance::valid(instance); + return instance.moveOutAsUniquePtr(); + }); }); } private: - std::optional> tryUniqueLock() + template auto safeAction(TAction action) { - const auto mutexPtr = getInstanceProvider().tryGetSyncMutex(); - return mutexPtr ? std::make_optional(std::unique_lock{*mutexPtr}) : std::nullopt; + if (const auto mutexPtr = getInstanceProvider().tryGetSyncMutex()) + { + std::lock_guard lock{*mutexPtr}; + return action(); + } + return action(); } }; } // namespace sb::di From 134e59fd93fd01520f87846b55b9025f5b1a4ed2 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 4 May 2024 12:50:41 +0200 Subject: [PATCH 05/12] fix win compilation --- Include/SevenBit/DI/ServiceProvider.hpp | 36 +++++++++++++------------ 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index f97f2eb..db4ce93 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -16,6 +16,7 @@ namespace sb::di class ServiceProvider { IServiceInstanceProvider::Ptr _instanceProvider; + std::recursive_mutex *_syncMutex = nullptr; public: using Ptr = std::unique_ptr; @@ -27,7 +28,8 @@ namespace sb::di : _instanceProvider(std::move(instanceProvider)) { details::Require::notNull(_instanceProvider); - getInstanceProvider().init(*this); + _instanceProvider->init(*this); + _syncMutex = _instanceProvider->tryGetSyncMutex(); } ServiceProvider(const ServiceProvider &parent) = delete; @@ -97,7 +99,7 @@ namespace sb::di */ template TService *tryGetService() { - return safeAction([&] -> TService * { + return safeAction([&]() -> TService * { if (const auto instancePtr = getInstanceProvider().tryGetInstance(typeid(TService)); instancePtr && *instancePtr) { @@ -121,7 +123,7 @@ namespace sb::di */ template TService *tryGetKeyedService(const std::string_view serviceKey) { - return safeAction([&] -> TService * { + return safeAction([&]() -> TService * { if (const auto instancePtr = getInstanceProvider().tryGetKeyedInstance(typeid(TService), serviceKey); instancePtr && *instancePtr) { @@ -145,7 +147,7 @@ namespace sb::di */ template TService &getService() { - return *safeAction([&] -> TService * { + return *safeAction([&]() -> TService * { auto &instance = getInstanceProvider().getInstance(typeid(TService)); details::RequireInstance::valid(instance); return instance.getAs(); @@ -167,7 +169,7 @@ namespace sb::di */ template TService &getKeyedService(const std::string_view serviceKey) { - return *safeAction([&] -> TService * { + return *safeAction([&]() -> TService * { auto &instance = getInstanceProvider().getKeyedInstance(typeid(TService), serviceKey); details::RequireInstance::valid(instance); return instance.getAs(); @@ -190,7 +192,7 @@ namespace sb::di */ template std::vector getServices() { - return safeAction([&] -> std::vector { + return safeAction([&]() -> std::vector { if (auto instancesPtr = getInstanceProvider().tryGetInstances(typeid(TService))) { return instancesPtr->map([](const ServiceInstance &instance) { @@ -219,7 +221,7 @@ namespace sb::di */ template std::vector getKeyedServices(const std::string_view serviceKey) { - return safeAction([&] -> std::vector { + return safeAction([&]() -> std::vector { if (auto instancesPtr = getInstanceProvider().tryGetKeyedInstances(typeid(TService), serviceKey)) { return instancesPtr->map([](const ServiceInstance &instance) { @@ -244,7 +246,7 @@ namespace sb::di */ template std::unique_ptr tryCreateService() { - return safeAction([&] -> std::unique_ptr { + return safeAction([&]() -> std::unique_ptr { if (auto instance = getInstanceProvider().tryCreateInstance(typeid(TService))) { return instance.moveOutAsUniquePtr(); @@ -267,7 +269,7 @@ namespace sb::di */ template std::unique_ptr tryCreateKeyedService(const std::string_view serviceKey) { - return safeAction([&] -> std::unique_ptr { + return safeAction([&]() -> std::unique_ptr { if (auto instance = getInstanceProvider().tryCreateKeyedInstance(typeid(TService), serviceKey)) { return instance.moveOutAsUniquePtr(); @@ -290,7 +292,7 @@ namespace sb::di */ template std::unique_ptr createService() { - return safeAction([&] -> std::unique_ptr { + return safeAction([&]() -> std::unique_ptr { auto instance = getInstanceProvider().createInstance(typeid(TService)); details::RequireInstance::valid(instance); return instance.moveOutAsUniquePtr(); @@ -312,7 +314,7 @@ namespace sb::di */ template std::unique_ptr createKeyedService(const std::string_view serviceKey) { - return safeAction([&] -> std::unique_ptr { + return safeAction([&]() -> std::unique_ptr { auto instance = getInstanceProvider().createKeyedInstance(typeid(TService), serviceKey); details::RequireInstance::valid(instance); return instance.moveOutAsUniquePtr(); @@ -333,7 +335,7 @@ namespace sb::di */ template TService createServiceInPlace() { - return safeAction([&] -> TService { + return safeAction([&]() -> TService { auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService)); details::RequireInstance::valid(instance); if constexpr (std::is_move_constructible_v) @@ -362,7 +364,7 @@ namespace sb::di */ template TService createKeyedServiceInPlace(const std::string_view serviceKey) { - return safeAction([&] -> TService { + return safeAction([&]() -> TService { auto instance = getInstanceProvider().createKeyedInstanceInPlace(typeid(TService), serviceKey); details::RequireInstance::valid(instance); if constexpr (std::is_move_constructible_v) @@ -392,7 +394,7 @@ namespace sb::di */ template std::vector> createServices() { - return safeAction([&] -> std::vector> { + return safeAction([&]() -> std::vector> { auto instances = getInstanceProvider().tryCreateInstances(typeid(TService)); return instances.map([&](ServiceInstance &instance) { details::RequireInstance::valid(instance); @@ -419,7 +421,7 @@ namespace sb::di template std::vector> createKeyedServices(const std::string_view serviceKey) { - return safeAction([&] -> std::vector> { + return safeAction([&]() -> std::vector> { auto instances = getInstanceProvider().tryCreateKeyedInstances(typeid(TService), serviceKey); return instances.map([&](ServiceInstance &instance) { details::RequireInstance::valid(instance); @@ -431,9 +433,9 @@ namespace sb::di private: template auto safeAction(TAction action) { - if (const auto mutexPtr = getInstanceProvider().tryGetSyncMutex()) + if (_syncMutex) { - std::lock_guard lock{*mutexPtr}; + std::lock_guard lock{*_syncMutex}; return action(); } return action(); From 3a2340858810dbd7ede4d7a05cae3825722b0d49 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 4 May 2024 18:55:55 +0200 Subject: [PATCH 06/12] update thread safe code --- .../DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp | 6 +++++- .../SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp | 2 +- .../DI/Details/Core/ServiceInstanceProviderRoot.hpp | 5 ----- Include/SevenBit/DI/ServiceProvider.hpp | 6 +++--- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp index f684349..05de8bb 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp @@ -10,12 +10,16 @@ namespace sb::di::details : ServiceInstanceProvider(*this, options), _descriptorsMap(options.checkServiceGlobalUniqueness), _singletons(options.strongDestructionOrder) { - _descriptorsMap.seal(); } INLINE void ServiceInstanceProviderRoot::init(ServiceProvider &serviceProvider) { ServiceInstanceProvider::init(serviceProvider); + _descriptorsMap.seal(); + if (getOptions().threadSafe) + { + _mutex = std::make_unique(); + } if (getOptions().prebuildSingletons) { prebuildSingletons(); diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 6a3a840..33ea0cb 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -18,9 +18,9 @@ namespace sb::di::details class EXPORT ServiceInstanceProvider : public IServiceInstanceProvider { ServiceProviderOptions _options; + IServiceInstanceProviderRoot &_root; ServiceInstancesCreator _instancesCreator; ServiceAliasesCreator _aliasesCreator; - IServiceInstanceProviderRoot &_root; ServiceInstancesMap _scoped; public: diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp index 594311d..a051681 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp @@ -27,11 +27,6 @@ namespace sb::di::details _descriptorsMap(begin, end, options.checkServiceGlobalUniqueness), _singletons(options.strongDestructionOrder) { - if (options.threadSafe) - { - _mutex = std::make_unique(); - } - _descriptorsMap.seal(); } void init(ServiceProvider &serviceProvider) override; diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index db4ce93..a49301c 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -32,11 +32,11 @@ namespace sb::di _syncMutex = _instanceProvider->tryGetSyncMutex(); } - ServiceProvider(const ServiceProvider &parent) = delete; + ServiceProvider(const ServiceProvider &) = delete; ServiceProvider(ServiceProvider &&) = delete; - ServiceProvider &operator=(const ServiceProvider &parent) = delete; - ServiceProvider &operator=(ServiceProvider &&parent) = delete; + ServiceProvider &operator=(const ServiceProvider &) = delete; + ServiceProvider &operator=(ServiceProvider &&) = delete; /** * @brief Returns inner service instance provider From a8e2799ad710ce167d79bd7ec840f20aebf5c7d2 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Mon, 6 May 2024 17:33:58 +0200 Subject: [PATCH 07/12] update thread safe code --- .../Containers/Impl/ServiceInstancesMap.hpp | 4 +- README.md | 8 +- Tests/Integration/ThreadSafeTest.cpp | 80 +++++++++++++++++++ 3 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 Tests/Integration/ThreadSafeTest.cpp diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp index df48a37..1a8d494 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp @@ -42,9 +42,9 @@ namespace sb::di::details { for (auto it = _constructionOrder.rbegin(); it != _constructionOrder.rend(); ++it) { - if (const auto list = findInstances(*it)) + if (const auto listPtr = findInstances(*it)) { - list->clear(); + listPtr->clear(); } } } diff --git a/README.md b/README.md index 54db97f..0e0b81a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@

- Documentation & Examples + Documentation & Examples

@@ -52,6 +52,10 @@ The library is officially supported on the following platforms: If you notice any problems/bugs, please file an issue on the repository GitHub Issue Tracker. Pull requests containing fixes are welcome! +## Documentation + +https://7bitDI.readthedocs.io + ## Installation ### There are a few ways of installation: @@ -230,6 +234,6 @@ actionA, actionB executed. ``` More examples and tutorials are available on the -[Documentation & Examples](https://7bitDI.readthedocs.io/en/latest/index.html) page +[Documentation & Examples](https://7bitDI.readthedocs.io) page @7bitcoder Sylwester Dawida 2023 diff --git a/Tests/Integration/ThreadSafeTest.cpp b/Tests/Integration/ThreadSafeTest.cpp new file mode 100644 index 0000000..c9eb1a2 --- /dev/null +++ b/Tests/Integration/ThreadSafeTest.cpp @@ -0,0 +1,80 @@ +#include +#include + +#include "../Helpers/Classes/Basic.hpp" +#include "../Helpers/Classes/CirularDependency.hpp" +#include "../Helpers/Classes/Complex.hpp" +#include +#include + +class ThreadSafeTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + ThreadSafeTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~ThreadSafeTest() override = default; + + static void TearDownTestSuite() {} +}; + +void getSafeServices(sb::di::ServiceProvider &provider) +{ + auto &service1 = provider.getService(); + auto &service2 = provider.getService(); + auto service3 = provider.createService(); + auto &service4 = provider.getService(); + auto &service5 = provider.getService(); + auto &service6 = provider.getService(); + + EXPECT_EQ(service1.number(), 1); + EXPECT_EQ(service2.number(), 2); + EXPECT_EQ(service3->number(), 3); + EXPECT_EQ(service4.number(), 4); + EXPECT_EQ(service5.number(), 5); + EXPECT_EQ(service6.number(), 6); + EXPECT_EQ(service2.getOne(), &service1); + EXPECT_EQ(service3->getOne(), &service1); + EXPECT_EQ(service3->getTwo(), &service2); + EXPECT_EQ(service4.getOne(), &service1); + EXPECT_EQ(service4.getTwo(), &service2); + EXPECT_NE(service4.getThree().get(), service3.get()); + EXPECT_EQ(service5.getOne(), &service1); + EXPECT_EQ(service5.getTwo(), &service2); + EXPECT_NE(service5.makeThree(), service3); + EXPECT_EQ(&service6.getOne(), &service1); + EXPECT_EQ(&service6.getTwo(), &service2); + EXPECT_FALSE(service6.getNonExisting()); + EXPECT_NE(service6.makeThree(), service3); +} + +TEST_F(ThreadSafeTest, ShouldGetSafeServices) +{ + sb::di::ServiceProviderOptions options; + options.threadSafe = true; + + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addTransient() + .addScoped() + .addScoped() + .addScoped() + .buildServiceProvider(options); + + std::vector threads; + constexpr size_t maxThreads = 50; + for (size_t i = 0; i < maxThreads; ++i) + { + threads.emplace_back(getSafeServices, std::ref(provider)); + } + for (auto &th : threads) + { + th.join(); + } +} From 3c8ddda81dd2b271d0575aa330de6bce4b91183c Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Tue, 7 May 2024 16:35:55 +0200 Subject: [PATCH 08/12] update docs with thread safe --- .../configuring-service-provider.rst | 2 +- Docs/getting-started.rst | 10 +++++++++ Examples/Guides/ConfiguredServiceProvider.cpp | 1 + Include/SevenBit/DI/ServiceProvider.hpp | 6 ++---- README.md | 21 +++++++++++++------ Tests/Integration/ThreadSafeTest.cpp | 6 ++---- 6 files changed, 31 insertions(+), 15 deletions(-) diff --git a/Docs/advanced-guides/configuring-service-provider.rst b/Docs/advanced-guides/configuring-service-provider.rst index c90fca8..786b8c6 100644 --- a/Docs/advanced-guides/configuring-service-provider.rst +++ b/Docs/advanced-guides/configuring-service-provider.rst @@ -11,7 +11,7 @@ read comment documentation for details: :language: C++ Pass the custom options to the ServiceCollection buildServiceProvider method to change produced -service provider behaviour +service provider behavior .. literalinclude:: ../../Examples/Guides/ConfiguredServiceProvider.cpp :caption: Examples/Guides/ConfiguredServiceProvider diff --git a/Docs/getting-started.rst b/Docs/getting-started.rst index 79fb6e7..ef0785b 100644 --- a/Docs/getting-started.rst +++ b/Docs/getting-started.rst @@ -1,6 +1,16 @@ Getting Started ========================== +Main Features +-------------------- + +* Implementation separation +* Multiple implementations support +* Keyed services +* Service aliases +* Thread safe support +* Strong destruction order support + Supported Platforms -------------------- diff --git a/Examples/Guides/ConfiguredServiceProvider.cpp b/Examples/Guides/ConfiguredServiceProvider.cpp index 2b7c8c7..17a67a4 100644 --- a/Examples/Guides/ConfiguredServiceProvider.cpp +++ b/Examples/Guides/ConfiguredServiceProvider.cpp @@ -39,6 +39,7 @@ int main() options.strongDestructionOrder = true; options.prebuildSingletons = true; options.checkServiceGlobalUniqueness = false; + options.threadSafe = true; ServiceProvider provider = ServiceCollection{} .addSingleton() diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index a49301c..8932be4 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -23,6 +23,8 @@ namespace sb::di /** * @brief Constructs service provider with specified instance provider + * @details If service instance provider is nullptr, constructor throws exception + * @throws sb::di::NullPointerException */ explicit ServiceProvider(IServiceInstanceProvider::Ptr instanceProvider) : _instanceProvider(std::move(instanceProvider)) @@ -40,15 +42,11 @@ namespace sb::di /** * @brief Returns inner service instance provider - * @details If service instance provider is nullptr, method throws exception - * @throws sb::di::NullPointerException */ [[nodiscard]] const IServiceInstanceProvider &getInstanceProvider() const { return *_instanceProvider; } /** * @brief Returns inner service instance provider - * @details If service instance provider is nullptr, method throws exception - * @throws sb::di::NullPointerException */ IServiceInstanceProvider &getInstanceProvider() { return *_instanceProvider; } diff --git a/README.md b/README.md index 0e0b81a..b5ad4ea 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,14 @@
-## Built With +## Main Features -- [Google Test](https://github.com/google/googletest) -- [Google Benchmark](https://github.com/google/benchmark) -- [Sphinx](https://www.sphinx-doc.org/en/master/) -- [Breathe](https://breathe.readthedocs.io/en/latest/) -- [Quom](https://pypi.org/project/quom/) +- Implementation separation +- Multiple implementations support +- Keyed services +- Service aliases +- Thread safe support +- Strong destruction order support ## Supported Platforms @@ -236,4 +237,12 @@ actionA, actionB executed. More examples and tutorials are available on the [Documentation & Examples](https://7bitDI.readthedocs.io) page +## Built With + +- [Google Test](https://github.com/google/googletest) +- [Google Benchmark](https://github.com/google/benchmark) +- [Sphinx](https://www.sphinx-doc.org/en/master/) +- [Breathe](https://breathe.readthedocs.io/en/latest/) +- [Quom](https://pypi.org/project/quom/) + @7bitcoder Sylwester Dawida 2023 diff --git a/Tests/Integration/ThreadSafeTest.cpp b/Tests/Integration/ThreadSafeTest.cpp index c9eb1a2..0211305 100644 --- a/Tests/Integration/ThreadSafeTest.cpp +++ b/Tests/Integration/ThreadSafeTest.cpp @@ -1,10 +1,7 @@ #include #include -#include "../Helpers/Classes/Basic.hpp" -#include "../Helpers/Classes/CirularDependency.hpp" #include "../Helpers/Classes/Complex.hpp" -#include #include class ThreadSafeTest : public testing::Test @@ -67,8 +64,9 @@ TEST_F(ThreadSafeTest, ShouldGetSafeServices) .addScoped() .buildServiceProvider(options); - std::vector threads; constexpr size_t maxThreads = 50; + std::vector threads; + threads.reserve(maxThreads); for (size_t i = 0; i < maxThreads; ++i) { threads.emplace_back(getSafeServices, std::ref(provider)); From 68a1661b249508027ef6b46aeb40bdee2d1e5bfe Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Tue, 7 May 2024 23:33:32 +0200 Subject: [PATCH 09/12] update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b5ad4ea..665910c 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ ## Main Features - Implementation separation -- Multiple implementations support +- Multiple implementations - Keyed services - Service aliases -- Thread safe support -- Strong destruction order support +- Thread safe +- Strong destruction order ## Supported Platforms From 11c03d1f5a500ef6d5ed6f3f391c07b809c749ef Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 12 May 2024 11:01:53 +0200 Subject: [PATCH 10/12] update docs and bump version --- CMakeLists.txt | 60 +++++++++---------- Docs/advanced-guides.rst | 1 - .../injected-utility-class.rst | 12 ++-- .../register-utility-class.rst | 6 +- Docs/advanced-guides/using-aliases.rst | 4 +- Docs/basic-guides.rst | 1 + .../configuring-service-provider.rst | 2 +- Docs/conf.py | 2 +- Docs/getting-started.rst | 14 ++--- Include/SevenBit/DI/CmakeDef.hpp | 2 +- README.md | 6 +- 11 files changed, 55 insertions(+), 55 deletions(-) rename Docs/{advanced-guides => basic-guides}/configuring-service-provider.rst (95%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e5854f..8c3fb42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.15.0) set(_7BIT_DI_LIBRARY 7bitDI) set(_7BIT_DI_VERSION_MAJOR 3) -set(_7BIT_DI_VERSION_MINOR 2) +set(_7BIT_DI_VERSION_MINOR 3) set(_7BIT_DI_VERSION_PATCH 0) set(_7BIT_DI_VERSION ${_7BIT_DI_VERSION_MAJOR}.${_7BIT_DI_VERSION_MINOR}.${_7BIT_DI_VERSION_PATCH}) @@ -12,9 +12,9 @@ project(${_7BIT_DI_LIBRARY} LANGUAGES CXX VERSION ${_7BIT_DI_VERSION}) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Cmake") -if (NOT CMAKE_CXX_STANDARD) +if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 17) -endif () +endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -26,29 +26,29 @@ include_directories(${_7BIT_DI_INCLUDE_DIR}) add_subdirectory(Source) -if (_7BIT_DI_BUILD_UNIT_TESTS OR _7BIT_DI_BUILD_INTEGRATION_TESTS OR _7BIT_DI_BUILD_E2E_TESTS) +if(_7BIT_DI_BUILD_UNIT_TESTS OR _7BIT_DI_BUILD_INTEGRATION_TESTS OR _7BIT_DI_BUILD_E2E_TESTS) enable_testing() add_subdirectory(Tests) -endif () +endif() -if (_7BIT_DI_BUILD_DOCS) +if(_7BIT_DI_BUILD_DOCS) add_subdirectory(Docs) -endif () +endif() -if (_7BIT_DI_BUILD_EXAMPLES) +if(_7BIT_DI_BUILD_EXAMPLES) add_subdirectory(Examples) -endif () +endif() -if (_7BIT_DI_BUILD_BENCHMARKS) +if(_7BIT_DI_BUILD_BENCHMARKS) add_subdirectory(Benchmarks) -endif () +endif() -if (_7BIT_DI_BUILD_SINGLE_HEADER) +if(_7BIT_DI_BUILD_SINGLE_HEADER) add_subdirectory(SingleHeader) -endif () +endif() -if (_7BIT_DI_INSTALL) +if(_7BIT_DI_INSTALL) set(PROJECT_CONFIG_IN ${CMAKE_CURRENT_SOURCE_DIR}/Cmake/7bitDIConfig.cmake.in) set(PROJECT_CONFIG_OUT ${CMAKE_CURRENT_BINARY_DIR}/7bitDIConfig.cmake) set(CONFIG_TARGETS_FILE 7bitDIConfigTargets.cmake) @@ -58,29 +58,29 @@ if (_7BIT_DI_INSTALL) install(DIRECTORY ${_7BIT_DI_INCLUDE_DIR}/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install( - TARGETS 7bitDI - EXPORT 7bitDI - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + TARGETS 7bitDI + EXPORT 7bitDI + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) export( - TARGETS 7bitDI - NAMESPACE 7bitDI:: - FILE ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_TARGETS_FILE}) + TARGETS 7bitDI + NAMESPACE 7bitDI:: + FILE ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_TARGETS_FILE}) install( - EXPORT 7bitDI - EXPORT 7bitDI - DESTINATION ${EXPORT_DEST_DIR} - NAMESPACE 7bitDI:: - NAMESPACE 7bitDI:: - FILE ${CONFIG_TARGETS_FILE}) + EXPORT 7bitDI + EXPORT 7bitDI + DESTINATION ${EXPORT_DEST_DIR} + NAMESPACE 7bitDI:: + NAMESPACE 7bitDI:: + FILE ${CONFIG_TARGETS_FILE}) include(CMakePackageConfigHelpers) configure_package_config_file(${PROJECT_CONFIG_IN} ${PROJECT_CONFIG_OUT} - INSTALL_DESTINATION ${EXPORT_DEST_DIR}) + INSTALL_DESTINATION ${EXPORT_DEST_DIR}) write_basic_package_version_file(${VERSIONS_CONFIG_FILE} COMPATIBILITY SameMajorVersion) @@ -89,4 +89,4 @@ if (_7BIT_DI_INSTALL) export(PACKAGE 7bitDI) include(CPack) -endif () +endif() diff --git a/Docs/advanced-guides.rst b/Docs/advanced-guides.rst index 0eeae13..b26ea9a 100644 --- a/Docs/advanced-guides.rst +++ b/Docs/advanced-guides.rst @@ -11,5 +11,4 @@ Advanced Guides advanced-guides/using-aliases advanced-guides/register-utility-class advanced-guides/injected-utility-class - advanced-guides/configuring-service-provider advanced-guides/building-library diff --git a/Docs/advanced-guides/injected-utility-class.rst b/Docs/advanced-guides/injected-utility-class.rst index 5ceaf89..36f0558 100644 --- a/Docs/advanced-guides/injected-utility-class.rst +++ b/Docs/advanced-guides/injected-utility-class.rst @@ -1,16 +1,16 @@ Injected Utility Class ======================================== -Library provides also Injected_ utility class. -This base class has inject() method that can be used to inject services in simple inline way, also -there are InjectedSingleton, InjectedScoped and InjectedTransient base classes that are inheriting -from Injected and Registered classes to combine these two features. Injected class has also method -getProvider(), raw provider can be used to get keyed services for example. +The library provides also Injected_ utility class. +This base class has inject() method that can be used to inject services in a simple inline way, also +there are InjectedSingleton, InjectedScoped and InjectedTransient base classes that inherit +from Injected and Registered classes to combine these two features. The injected class has also a method +getProvider(), the raw provider can be used to get keyed services for example. .. _Injected: ../reference/di/utils/injected.html .. note:: - Class should inherit Injected constructor with 'using Injected::Injected;' in public section + The class should inherit Injected constructor with 'using Injected::Injected;' in the public section .. literalinclude:: ../../Examples/Guides/InjectedUtilityClass.cpp :caption: Examples/Guides/InjectedUtilityClass diff --git a/Docs/advanced-guides/register-utility-class.rst b/Docs/advanced-guides/register-utility-class.rst index ba17282..079de67 100644 --- a/Docs/advanced-guides/register-utility-class.rst +++ b/Docs/advanced-guides/register-utility-class.rst @@ -1,13 +1,13 @@ Register Utility Class ======================================== -Library provides simple template RegisterService_ utility class. -This base class can be used to automatically register class in service collection with use of specialised TRegisterer. +The library provides a simple template RegisterService_ utility class. +This base class can be used to automatically register class in service collection with the use of a specialized TRegisterer. There are already created aliases RegisterSingleton_, RegisterScoped_, RegisterTransient_ that are registering services in GlobalServices_ singleton. .. note:: - Class should inherit Injected constructor with 'using Injected::Injected;' in public section + The class should inherit Injected constructor with 'using Injected::Injected;' in the public section .. _RegisterService: ../reference/di/utils/register.html .. _RegisterSingleton: ../reference/di/utils/register.html diff --git a/Docs/advanced-guides/using-aliases.rst b/Docs/advanced-guides/using-aliases.rst index 5d82c33..4a2d9bb 100644 --- a/Docs/advanced-guides/using-aliases.rst +++ b/Docs/advanced-guides/using-aliases.rst @@ -2,11 +2,11 @@ Using Aliases ======================================== With the use of aliases, one service can be injected through its multiple base classes, also aliases can be chained. -In case of injecting multiple aliases all real services will be fetched. +In case of injecting multiple aliases, all real services will be fetched. .. warning:: Using aliases is resource intensive, especially for injecting transient and multiple services, provider recursively - traverses through aliases chain to find proper service. Mixing scoped and singleton aliases for same base type will + traverses through the aliases chain to find the proper service. Mixing scoped and singleton aliases for the same base type will lead to undefined behavior .. literalinclude:: ../../Examples/Guides/ServiceAliases.cpp diff --git a/Docs/basic-guides.rst b/Docs/basic-guides.rst index 81c6ed4..62380f3 100644 --- a/Docs/basic-guides.rst +++ b/Docs/basic-guides.rst @@ -12,3 +12,4 @@ Basic Guides basic-guides/injecting-multiple-services basic-guides/injection-rules basic-guides/injecting-service-provider + basic-guides/configuring-service-provider diff --git a/Docs/advanced-guides/configuring-service-provider.rst b/Docs/basic-guides/configuring-service-provider.rst similarity index 95% rename from Docs/advanced-guides/configuring-service-provider.rst rename to Docs/basic-guides/configuring-service-provider.rst index 786b8c6..11d1f67 100644 --- a/Docs/advanced-guides/configuring-service-provider.rst +++ b/Docs/basic-guides/configuring-service-provider.rst @@ -10,7 +10,7 @@ read comment documentation for details: :caption: Include/SevenBit/DI/ServiceProviderOptions.hpp :language: C++ -Pass the custom options to the ServiceCollection buildServiceProvider method to change produced +Pass the custom options to the ServiceCollection buildServiceProvider method to change the produced service provider behavior .. literalinclude:: ../../Examples/Guides/ConfiguredServiceProvider.cpp diff --git a/Docs/conf.py b/Docs/conf.py index 5ec2320..e646c4f 100644 --- a/Docs/conf.py +++ b/Docs/conf.py @@ -12,7 +12,7 @@ def createIfNotExists(path): project = "7bitDI" copyright = "2023, 7BitCoder Sylwester Dawida" author = "Sylwester Dawida" -version = "3.2.0" +version = "3.3.0" extensions = [ "sphinx.ext.autodoc", diff --git a/Docs/getting-started.rst b/Docs/getting-started.rst index ef0785b..b942949 100644 --- a/Docs/getting-started.rst +++ b/Docs/getting-started.rst @@ -5,11 +5,11 @@ Main Features -------------------- * Implementation separation -* Multiple implementations support +* Multiple implementations * Keyed services * Service aliases -* Thread safe support -* Strong destruction order support +* Thread safe +* Strong destruction order Supported Platforms -------------------- @@ -37,8 +37,8 @@ Installation **There are a few ways of installation:** -#. Using Cmake fetch content api - Recommended - Update CMakeLists.txt file with following code +#. Using Cmake fetch content API - Recommended + Update CMakeLists.txt file with the following code .. code-block:: Cmake @@ -46,7 +46,7 @@ Installation FetchContent_Declare( 7bitDI GIT_REPOSITORY https://github.com/7bitcoder/7bitDI.git - GIT_TAG v3.2.0 + GIT_TAG v3.3.0 ) FetchContent_MakeAvailable(7bitDI) @@ -58,7 +58,7 @@ Installation .. code-block:: Txt [requires] - 7bitdi/3.2.0 + 7bitdi/3.3.0 change the version to newer if available, then run the command: diff --git a/Include/SevenBit/DI/CmakeDef.hpp b/Include/SevenBit/DI/CmakeDef.hpp index 9dcd81a..56f8e83 100644 --- a/Include/SevenBit/DI/CmakeDef.hpp +++ b/Include/SevenBit/DI/CmakeDef.hpp @@ -13,5 +13,5 @@ #endif #define _7BIT_DI_VERSION_MAJOR 3 -#define _7BIT_DI_VERSION_MINOR 2 +#define _7BIT_DI_VERSION_MINOR 3 /* #undef _7BIT_DI_VERSION_PATCH */ diff --git a/README.md b/README.md index 665910c..6aafa3b 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ https://7bitDI.readthedocs.io ### There are a few ways of installation: -### 1. Using Cmake fetch content api - Recommended +### 1. Using Cmake fetch content API - Recommended Update CMakeLists.txt file with the following code @@ -70,7 +70,7 @@ include(FetchContent) FetchContent_Declare( 7bitDI GIT_REPOSITORY https://github.com/7bitcoder/7bitDI.git - GIT_TAG v3.2.0 + GIT_TAG v3.3.0 ) FetchContent_MakeAvailable(7bitDI) @@ -83,7 +83,7 @@ Download and install A [Conan](https://conan.io/), and create conanfile.txt in t ``` [requires] -7bitdi/3.2.0 +7bitdi/3.3.0 ``` change the version to newer if available, then run the command: From 87dd9e8cba62fecb809ec24562c090804e725f8b Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 12 May 2024 11:27:38 +0200 Subject: [PATCH 11/12] update cmake main --- CMakeLists.txt | 58 +++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c3fb42..0a394f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,9 +12,9 @@ project(${_7BIT_DI_LIBRARY} LANGUAGES CXX VERSION ${_7BIT_DI_VERSION}) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Cmake") -if(NOT CMAKE_CXX_STANDARD) +if (NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 17) -endif() +endif () set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -26,29 +26,29 @@ include_directories(${_7BIT_DI_INCLUDE_DIR}) add_subdirectory(Source) -if(_7BIT_DI_BUILD_UNIT_TESTS OR _7BIT_DI_BUILD_INTEGRATION_TESTS OR _7BIT_DI_BUILD_E2E_TESTS) +if (_7BIT_DI_BUILD_UNIT_TESTS OR _7BIT_DI_BUILD_INTEGRATION_TESTS OR _7BIT_DI_BUILD_E2E_TESTS) enable_testing() add_subdirectory(Tests) -endif() +endif () -if(_7BIT_DI_BUILD_DOCS) +if (_7BIT_DI_BUILD_DOCS) add_subdirectory(Docs) -endif() +endif () -if(_7BIT_DI_BUILD_EXAMPLES) +if (_7BIT_DI_BUILD_EXAMPLES) add_subdirectory(Examples) -endif() +endif () -if(_7BIT_DI_BUILD_BENCHMARKS) +if (_7BIT_DI_BUILD_BENCHMARKS) add_subdirectory(Benchmarks) -endif() +endif () -if(_7BIT_DI_BUILD_SINGLE_HEADER) +if (_7BIT_DI_BUILD_SINGLE_HEADER) add_subdirectory(SingleHeader) -endif() +endif () -if(_7BIT_DI_INSTALL) +if (_7BIT_DI_INSTALL) set(PROJECT_CONFIG_IN ${CMAKE_CURRENT_SOURCE_DIR}/Cmake/7bitDIConfig.cmake.in) set(PROJECT_CONFIG_OUT ${CMAKE_CURRENT_BINARY_DIR}/7bitDIConfig.cmake) set(CONFIG_TARGETS_FILE 7bitDIConfigTargets.cmake) @@ -58,29 +58,29 @@ if(_7BIT_DI_INSTALL) install(DIRECTORY ${_7BIT_DI_INCLUDE_DIR}/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install( - TARGETS 7bitDI - EXPORT 7bitDI - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + TARGETS 7bitDI + EXPORT 7bitDI + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) export( - TARGETS 7bitDI - NAMESPACE 7bitDI:: - FILE ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_TARGETS_FILE}) + TARGETS 7bitDI + NAMESPACE 7bitDI:: + FILE ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_TARGETS_FILE}) install( - EXPORT 7bitDI - EXPORT 7bitDI - DESTINATION ${EXPORT_DEST_DIR} - NAMESPACE 7bitDI:: - NAMESPACE 7bitDI:: - FILE ${CONFIG_TARGETS_FILE}) + EXPORT 7bitDI + EXPORT 7bitDI + DESTINATION ${EXPORT_DEST_DIR} + NAMESPACE 7bitDI:: + NAMESPACE 7bitDI:: + FILE ${CONFIG_TARGETS_FILE}) include(CMakePackageConfigHelpers) configure_package_config_file(${PROJECT_CONFIG_IN} ${PROJECT_CONFIG_OUT} - INSTALL_DESTINATION ${EXPORT_DEST_DIR}) + INSTALL_DESTINATION ${EXPORT_DEST_DIR}) write_basic_package_version_file(${VERSIONS_CONFIG_FILE} COMPATIBILITY SameMajorVersion) @@ -89,4 +89,4 @@ if(_7BIT_DI_INSTALL) export(PACKAGE 7bitDI) include(CPack) -endif() +endif () From a02f34a26ad522115cf137d1f57a2d1a7d539b85 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 12 May 2024 11:47:08 +0200 Subject: [PATCH 12/12] remove gcc13 from macos --- .github/workflows/MacOs.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/MacOs.yml b/.github/workflows/MacOs.yml index 1091706..588d501 100644 --- a/.github/workflows/MacOs.yml +++ b/.github/workflows/MacOs.yml @@ -19,8 +19,7 @@ jobs: { tool: apple-clang }, { tool: gcc, ver: 10 }, { tool: gcc, ver: 11 }, - { tool: gcc, ver: 12 }, - { tool: gcc, ver: 13 } ] + { tool: gcc, ver: 12 } ] build_type: [ Release ] os: [ macos-12 ] std: [ 17 ]