This is an automated email from the ASF dual-hosted git repository. pnoltes pushed a commit to branch feature/cxx in repository https://gitbox.apache.org/repos/asf/celix.git
commit 41cb4b5be5239d11d57e0af68ea760d7bd328c93 Author: Pepijn Noltes <[email protected]> AuthorDate: Tue Jul 23 22:08:17 2019 +0200 CELIX-370: Update ServiceDependency implementation --- .../gtest/src/ComponentManager_tests.cc | 9 +- .../framework_cxx/include/celix/ComponentManager.h | 207 ++++++++++++++------- libs/framework_cxx/src/ComponentManager.cc | 31 ++- libs/registry/include/celix/ServiceRegistry.h | 2 +- 4 files changed, 169 insertions(+), 80 deletions(-) diff --git a/libs/framework_cxx/gtest/src/ComponentManager_tests.cc b/libs/framework_cxx/gtest/src/ComponentManager_tests.cc index f9a42ad..77dc8de 100644 --- a/libs/framework_cxx/gtest/src/ComponentManager_tests.cc +++ b/libs/framework_cxx/gtest/src/ComponentManager_tests.cc @@ -53,9 +53,16 @@ TEST_F(ComponentManagerTest, AddSvcDep) { class ISvc {}; celix::ComponentManager<Cmp> cmpMng{ctx, std::make_shared<Cmp>()}; - cmpMng.addServiceDependency(); //TODO + cmpMng.addServiceDependency<ISvc>() + .setRequired(true); cmpMng.enable(); EXPECT_TRUE(cmpMng.isEnabled()); + //dep not available -> cmp manager not resolved + EXPECT_FALSE(cmpMng.isResolved()); + + auto svcReg = ctx->registerService(std::make_shared<ISvc>()); + //dep available -> cmp manager resolved + EXPECT_TRUE(cmpMng.isResolved()); } \ No newline at end of file diff --git a/libs/framework_cxx/include/celix/ComponentManager.h b/libs/framework_cxx/include/celix/ComponentManager.h index 431b784..bfbd971 100644 --- a/libs/framework_cxx/include/celix/ComponentManager.h +++ b/libs/framework_cxx/include/celix/ComponentManager.h @@ -49,13 +49,15 @@ namespace celix { //TODO make friend of SvcDep void updateState(); protected: - GenericComponentManager(std::shared_ptr<BundleContext> _ctx, std::shared_ptr<void> cmpInstance) : ctx{std::move(_ctx)}, instance{std::move(cmpInstance)} {}; + GenericComponentManager(std::shared_ptr<BundleContext> _ctx) : ctx{std::move(_ctx)} {}; void removeServiceDependency(long serviceDependencyId); void setEnabled(bool enable); /**** Fields ****/ + std::shared_ptr<BundleContext> ctx; + mutable std::mutex mutex{}; //protects below ComponentState state = ComponentState::Disabled; bool enabled = false; @@ -64,11 +66,8 @@ namespace celix { std::function<void()> stop{}; std::function<void()> deinit{}; - std::shared_ptr<BundleContext> ctx; - std::shared_ptr<void> instance; - long nextServiceDependencyId = 1L; - std::unordered_map<long,GenericServiceDependency> serviceDependencies{}; + std::unordered_map<long,std::unique_ptr<GenericServiceDependency>> serviceDependencies{}; }; template<typename T> @@ -82,17 +81,21 @@ namespace celix { ComponentManager<T>& enable(); ComponentManager<T>& disable(); + std::shared_ptr<T> instance(); + ComponentManager<T>& setCallbacks( void (T::*init)(), void (T::*start)(), void (T::*stop)(), void (T::*deinit)()); -// template<typename I> -// ServiceDependency<T,I>& addServiceDependency(); + template<typename I> + ServiceDependency<T,I>& addServiceDependency(); // // template<typename F> // ServiceDependency<T,F>& addFunctionServiceDependency(const std::string &functionName); + private: + std::shared_ptr<T> inst; }; @@ -109,18 +112,26 @@ namespace celix { Cardinality getCardinality() const; bool getRequired() const; const std::string& getFilter() const; + void setEnable(bool enable); protected: - GenericServiceDependency(std::shared_ptr<BundleContext> ctx); + GenericServiceDependency( + std::shared_ptr<BundleContext> ctx, + std::function<void()> stateChangedCallback, + std::function<void()> enable, + std::function<void()> disable); //Fields + std::shared_ptr<BundleContext> ctx; + const std::function<void()> stateChangedCallback; + const std::function<void()> enable; + std::function<void()> disable; + mutable std::mutex mutex{}; //protects below bool required = false; std::string filter{}; Cardinality cardinality = Cardinality::One; std::vector<ServiceTracker> tracker{}; //max 1 - - std::shared_ptr<BundleContext> ctx; }; template<typename T, typename I> @@ -129,7 +140,7 @@ namespace celix { using ComponentType = T; using ServiceType = I; - ServiceDependency(std::shared_ptr<ComponentManager<T>> mng); + ServiceDependency(std::shared_ptr<BundleContext> ctx, std::function<void()> stateChangedCallback, std::function<std::shared_ptr<T>()> getCmpInstance); ~ServiceDependency() override = default; ServiceDependency<T,I>& setFilter(const std::string &filter); @@ -138,15 +149,25 @@ namespace celix { ServiceDependency<T,I>& setCallbacks(void (T::*set)(std::shared_ptr<I>)); ServiceDependency<T,I>& setCallbacks(void (T::*add)(std::shared_ptr<I>), void (T::*remove)(std::shared_ptr<I>)); //TODO update callback + //TODO callbacks with properties and owner + + ServiceDependency<T,I>& setFunctionCallbacks( + std::function<void(std::shared_ptr<I>, const celix::Properties &props, const celix::IResourceBundle &owner)> set, + std::function<void(std::shared_ptr<I>, const celix::Properties &props, const celix::IResourceBundle &owner)> add, + std::function<void(std::shared_ptr<I>, const celix::Properties &props, const celix::IResourceBundle &owner)> rem, + std::function<void(std::vector<std::tuple<std::shared_ptr<I>, const celix::Properties*, const celix::IResourceBundle *>> rankedServices)> update); - void enable(); - void disable(); + ServiceDependency<T,I>& enable(); + ServiceDependency<T,I>& disable(); bool isResolved(); private: - std::function<void(std::shared_ptr<I>)> set{}; - std::function<void(std::shared_ptr<I>)> add{}; - std::function<void(std::shared_ptr<I>)> rem{}; - std::shared_ptr<ComponentManager<T>> mng; + const std::function<std::shared_ptr<T>()> getCmpInstance; + + + std::function<void(std::shared_ptr<I> svc, const celix::Properties &props, const celix::IResourceBundle &owner)> set{}; + std::function<void(std::shared_ptr<I> svc, const celix::Properties &props, const celix::IResourceBundle &owner)> add{}; + std::function<void(std::shared_ptr<I> svc, const celix::Properties &props, const celix::IResourceBundle &owner)> rem{}; + std::function<void(std::vector<std::tuple<std::shared_ptr<I>, const celix::Properties*, const celix::IResourceBundle *>> rankedServices)> update{}; }; } @@ -155,8 +176,9 @@ namespace celix { /**************************** IMPLEMENTATION *************************************************************************/ template<typename T> -celix::ComponentManager<T>::ComponentManager(std::shared_ptr<BundleContext> ctx, std::shared_ptr<T> cmpInstance) : - GenericComponentManager(ctx, std::static_pointer_cast<void>(cmpInstance)) {} +celix::ComponentManager<T>::ComponentManager( + std::shared_ptr<BundleContext> ctx, + std::shared_ptr<T> cmpInstance) : GenericComponentManager{ctx}, inst{std::move(cmpInstance)} {} template<typename T> celix::ComponentManager<T>& celix::ComponentManager<T>::enable() { @@ -172,95 +194,138 @@ celix::ComponentManager<T>& celix::ComponentManager<T>::disable() { template<typename T> celix::ComponentManager<T>& celix::ComponentManager<T>::setCallbacks( - void (T::*init)(), - void (T::*start)(), - void (T::*stop)(), - void (T::*deinit)()) { + void (T::*memberInit)(), + void (T::*memberStart)(), + void (T::*memberStop)(), + void (T::*memberDeinit)()) { std::lock_guard<std::mutex> lck{mutex}; - auto initFunc = [this,init]() { - if (init) { - (this->instance->*init)(); + init = [this, memberInit]() { + if (memberInit) { + (this->instance()->*memberInit)(); } }; - auto startFunc = [this,start]() { - if (start) { - (this->instance->*start)(); + start = [this, memberStart]() { + if (memberStart) { + (this->instance()->*memberStart)(); } }; - auto stopFunc = [this,stop]() { - if (stop) { - (this->instance->*stop)(); + stop = [this, memberStop]() { + if (memberStop) { + (this->instance()->*memberStop)(); } }; - auto deinitFunc = [this,deinit]() { - if (deinit) { - (this->instance->*deinit)(); + deinit = [this, memberDeinit]() { + if (memberDeinit) { + (this->instance()->*memberDeinit)(); } }; + return *this; +} +template<typename T> +std::shared_ptr<T> celix::ComponentManager<T>::instance() { + return inst; } -template<typename T, typename I> -celix::ServiceDependency<T,I>::ServiceDependency(std::shared_ptr<ComponentManager<T>> _mng) : mng{std::move(_mng)} { - add = [this](std::shared_ptr<I>) { - mng->updateState(); - }; - rem = [this](std::shared_ptr<I>) { - mng->updateState(); - }; + +template<typename T> +template<typename I> +celix::ServiceDependency<T,I>& celix::ComponentManager<T>::addServiceDependency() { + auto *dep = new celix::ServiceDependency<T,I>{ctx, []{/*TODO*/}, [this]{return instance();}}; + std::lock_guard<std::mutex> lck{mutex}; + serviceDependencies[nextServiceDependencyId++] = std::unique_ptr<GenericServiceDependency>{dep}; + return *dep; } + + + + + + + template<typename T, typename I> -void celix::ServiceDependency<T,I>::enable() { - std::vector<celix::ServiceTracker> localTrackers{}; - { - std::lock_guard<std::mutex> lck{mutex}; - std::swap(localTrackers, tracker); - assert(tracker.size() == 0); +celix::ServiceDependency<T,I>::ServiceDependency( + std::shared_ptr<celix::BundleContext> _ctx, + std::function<void()> _stateChangedCallback, + std::function<std::shared_ptr<T>()> _getCmpInstance) : GenericServiceDependency{_ctx, _stateChangedCallback, [this]{enable();}, [this]{disable();}}, getCmpInstance{_getCmpInstance} {}; +template<typename T, typename I> +celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::enable() { + std::lock_guard<std::mutex> lck{mutex}; + if (tracker.size() == 0) { //disabled ServiceTrackerOptions<I> opts{}; opts.filter = this->filter; - opts.set = set; - opts.add = add; - opts.remove = rem; - + opts.setWithOwner = set; + opts.addWithOwner = add; + opts.removeWithOwner = rem; + opts.updateWithOwner = [this](std::vector<std::tuple<std::shared_ptr<I>, const celix::Properties*, const celix::IResourceBundle *>> rankedServices) { + if (this->update) { + //TODO lock? + this->update(std::move(rankedServices)); + } + this->stateChangedCallback(); + }; this->tracker.push_back(this->ctx->trackServices(opts)); } + return *this; +} +template<typename T, typename I> +celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::disable() { + std::lock_guard<std::mutex> lck{mutex}; + tracker.clear(); + return *this; } template<typename T, typename I> -void celix::ServiceDependency<T,I>::disable() { - std::vector<celix::ServiceTracker> localTrackers{}; - { - std::lock_guard<std::mutex> lck{mutex}; - std::swap(localTrackers, tracker); - assert(tracker.size() == 0); +celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::setFunctionCallbacks( + std::function<void(std::shared_ptr<I> svc, const celix::Properties &props, const celix::IResourceBundle &owner)> setArg, + std::function<void(std::shared_ptr<I> svc, const celix::Properties &props, const celix::IResourceBundle &owner)> addArg, + std::function<void(std::shared_ptr<I> svc, const celix::Properties &props, const celix::IResourceBundle &owner)> remArg, + std::function<void(std::vector<std::tuple<std::shared_ptr<I>, const celix::Properties*, const celix::IResourceBundle *>> rankedServices)> updateArg) { + + //TODO lock or disable? + set = {}; + add = {}; + rem = {}; + update = {}; + + if (setArg) { + set = std::move(setArg); + } + if (addArg) { + add = addArg; + } + if (remArg) { + rem = remArg; + } + if (updateArg) { + update = std::move(updateArg); } + return *this; } - template<typename T, typename I> celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::setCallbacks(void (T::*setfp)(std::shared_ptr<I>)) { std::lock_guard<std::mutex> lck{mutex}; - set = [this, setfp](std::shared_ptr<I> svc) { - (mng->instance->*setfp)(svc); + auto setFunc = [this, setfp](std::shared_ptr<I> svc, const celix::Properties &, const celix::IResourceBundle &) { + (getCmpInstance()->instance->*setfp)(svc); }; - return *this; + return setFunctionCallbacks(std::move(setFunc), {}, {}, {}); } + template<typename T, typename I> celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::setCallbacks(void (T::*addfp)(std::shared_ptr<I>), void (T::*remfp)(std::shared_ptr<I>)) { std::lock_guard<std::mutex> lck{mutex}; - add = [this, addfp](std::shared_ptr<I> svc) { - (mng->instance->*addfp)(svc); - mng->updateState(); + auto addFunc = [this, addfp](std::shared_ptr<I> svc, const celix::Properties &, const celix::IResourceBundle &) { + (getCmpInstance()->instance->*addfp)(svc); }; - rem = [this, remfp](std::shared_ptr<I> svc) { - (mng->instance->*remfp)(svc); - mng->updateState(); + auto remFunc = [this, remfp](std::shared_ptr<I> svc, const celix::Properties &, const celix::IResourceBundle &) { + (getCmpInstance()->instance->*remfp)(svc); }; - return *this; + return setFunctionCallbacks({}, std::move(addFunc), std::move(remFunc), {}); } template<typename T, typename I> @@ -285,4 +350,4 @@ celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::setCardinality(cel } -#endif //CXX_CELIX_PROPERTIES_H +#endif //CXX_CELIX_COMPONENT_MANAGER_H diff --git a/libs/framework_cxx/src/ComponentManager.cc b/libs/framework_cxx/src/ComponentManager.cc index b3b4205..f087b19 100644 --- a/libs/framework_cxx/src/ComponentManager.cc +++ b/libs/framework_cxx/src/ComponentManager.cc @@ -19,10 +19,16 @@ #include <iostream> +#include <celix/ComponentManager.h> + #include "celix/ComponentManager.h" -celix::GenericServiceDependency::GenericServiceDependency(std::shared_ptr<celix::BundleContext> _ctx) : ctx{_ctx} {} +celix::GenericServiceDependency::GenericServiceDependency( + std::shared_ptr<celix::BundleContext> _ctx, + std::function<void()> _stateChangedCallback, + std::function<void()> _enable, + std::function<void()> _disable) : ctx{_ctx}, stateChangedCallback{std::move(_stateChangedCallback)}, enable{std::move(_enable)}, disable{std::move(_disable)} {} bool celix::GenericServiceDependency::isResolved() const { @@ -49,6 +55,14 @@ const std::string &celix::GenericServiceDependency::getFilter() const { return filter; } +void celix::GenericServiceDependency::setEnable(bool e) { + if (e) { + enable(); + } else { + disable(); + } +} + celix::ComponentState celix::GenericComponentManager::getState() const { std::lock_guard<std::mutex> lck{mutex}; return state; @@ -62,11 +76,11 @@ bool celix::GenericComponentManager::isEnabled() const { bool celix::GenericComponentManager::isResolved() const { std::lock_guard<std::mutex> lck{mutex}; -// for (auto &pair : serviceDependencies) { -// if (!pair->second.isResolved()) { -// return false; -// } -// } + for (auto &pair : serviceDependencies) { + if (!pair.second->isResolved()) { + return false; + } + } return true; } @@ -78,6 +92,9 @@ void celix::GenericComponentManager::removeServiceDependency(long serviceDepende void celix::GenericComponentManager::setEnabled(bool e) { std::lock_guard<std::mutex> lck{mutex}; enabled = e; + for (auto &pair : serviceDependencies) { + pair.second->setEnable(e); + } } void celix::GenericComponentManager::updateState() { @@ -89,7 +106,7 @@ void celix::GenericComponentManager::updateState() { bool allDependenciesResolved = true; for (auto &pair : serviceDependencies) { - if (!pair.second.isResolved()) { + if (!pair.second->isResolved()) { allDependenciesResolved = false; break; } diff --git a/libs/registry/include/celix/ServiceRegistry.h b/libs/registry/include/celix/ServiceRegistry.h index c9a9a8e..4457d0e 100644 --- a/libs/registry/include/celix/ServiceRegistry.h +++ b/libs/registry/include/celix/ServiceRegistry.h @@ -601,7 +601,7 @@ inline celix::ServiceTracker celix::ServiceRegistry::trackServices(std::string s }; } - return trackAnyServices(std::move(svcName), std::move(opts), requester); + return trackAnyServices(std::move(svcName), std::move(opts), std::move(requester)); } #endif //CXX_CELIX_SERVICEREGISTRY_H
