You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2019/07/23 20:08:48 UTC

[celix] 02/02: CELIX-370: Update ServiceDependency implementation

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 <pe...@gmail.com>
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