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 2020/11/10 19:05:29 UTC
[celix] 01/01: Initial refactoring to add a build() call support
for the dependency manager (dm, components,
service provide and service dependencies)
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch feature/add_build_to_svc_dep_creation
in repository https://gitbox.apache.org/repos/asf/celix.git
commit d820c9edb5da0262bb7c93d4142a2a0a408d5a56
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Tue Nov 10 20:05:07 2020 +0100
Initial refactoring to add a build() call support for the dependency manager (dm, components, service provide and service dependencies)
---
libs/framework/gtest/src/dm_tests.cpp | 30 +++++
libs/framework/include/celix/dm/Component.h | 37 ++++--
libs/framework/include/celix/dm/Component_Impl.h | 127 ++++++++++++---------
.../framework/include/celix/dm/DependencyManager.h | 6 +-
.../include/celix/dm/DependencyManager_Impl.h | 13 ++-
.../framework/include/celix/dm/ServiceDependency.h | 27 ++++-
.../include/celix/dm/ServiceDependency_Impl.h | 81 ++++++++-----
7 files changed, 218 insertions(+), 103 deletions(-)
diff --git a/libs/framework/gtest/src/dm_tests.cpp b/libs/framework/gtest/src/dm_tests.cpp
index 18ed4e1..893ed14 100644
--- a/libs/framework/gtest/src/dm_tests.cpp
+++ b/libs/framework/gtest/src/dm_tests.cpp
@@ -75,3 +75,33 @@ TEST_F(DepenencyManagerTests, TestCheckActive) {
celix_dependencyManager_add(mng, cmp);
ASSERT_FALSE(celix_dependencyManager_areComponentsActive(mng));
}
+
+class TestComponent {
+
+};
+
+TEST_F(DepenencyManagerTests, OnlyActiveAfterBuildCheck) {
+ celix::dm::DependencyManager dm{ctx};
+ EXPECT_EQ(0, dm.getNrOfComponents());
+
+ auto& cmp = dm.createComponent<TestComponent>(std::make_shared<TestComponent>(), "test1");
+ EXPECT_EQ(0, dm.getNrOfComponents()); //dm not started yet / comp not build yet
+ EXPECT_TRUE(cmp.isValid());
+
+ cmp.build();
+ EXPECT_EQ(1, dm.getNrOfComponents()); //cmp "build", so active
+}
+
+TEST_F(DepenencyManagerTests, StartDmWillBuildCmp) {
+ celix::dm::DependencyManager dm{ctx};
+ EXPECT_EQ(0, dm.getNrOfComponents());
+
+ auto& cmp = dm.createComponent<TestComponent>(std::make_shared<TestComponent>(), "test1");
+ EXPECT_EQ(0, dm.getNrOfComponents()); //dm not started yet / comp not build yet
+ EXPECT_TRUE(cmp.isValid());
+
+ dm.start();
+ EXPECT_EQ(1, dm.getNrOfComponents()); //cmp "build", so active
+}
+
+//TODO add test where not all svc dependency are active and active them by a build call
diff --git a/libs/framework/include/celix/dm/Component.h b/libs/framework/include/celix/dm/Component.h
index 57b7959..a4eefab 100644
--- a/libs/framework/include/celix/dm/Component.h
+++ b/libs/framework/include/celix/dm/Component.h
@@ -26,15 +26,13 @@
#include <map>
#include <string>
#include <vector>
+#include <atomic>
namespace celix { namespace dm {
class BaseComponent {
- private:
- celix_bundle_context_t *context {nullptr};
- celix_dm_component_t *cCmp {nullptr};
public:
- BaseComponent(celix_bundle_context_t *con, const std::string &name) : context{con}, cCmp{nullptr} {
+ BaseComponent(celix_bundle_context_t *con, celix_dependency_manager_t* cdm, const std::string &name) : context{con}, cDepMan{cdm}, cCmp{nullptr} {
this->cCmp = celix_dmComponent_create(this->context, name.c_str());
celix_dmComponent_setImplementation(this->cCmp, this);
}
@@ -52,6 +50,22 @@ namespace celix { namespace dm {
* Returns the C bundle context
*/
celix_bundle_context_t* bundleContext() const { return this->context; }
+
+ void runBuild();
+ protected:
+ std::vector<std::shared_ptr<BaseServiceDependency>> dependencies{};
+
+ // 0 = service name
+ // 1 = service version
+ // 2 = properties
+ // 3 = is C++ service (true -> C++, false -> C)
+ // 4 = service pointer
+ std::vector<std::tuple<std::string, std::string, Properties, bool, void*>> inactiveProvidedServices{};
+ private:
+ celix_bundle_context_t* context;
+ celix_dependency_manager_t* cDepMan;
+ celix_dm_component_t *cCmp;
+ std::atomic<bool> cmpAddedToDepMan{false};
};
@@ -62,7 +76,6 @@ namespace celix { namespace dm {
std::unique_ptr<T> instance {nullptr};
std::shared_ptr<T> sharedInstance {nullptr};
std::vector<T> valInstance {};
- std::vector<std::shared_ptr<BaseServiceDependency>> dependencies {};
void (T::*initFp)() = {};
void (T::*startFp)() = {};
@@ -74,7 +87,7 @@ namespace celix { namespace dm {
int (T::*stopFpNoExc)() = {};
int (T::*deinitFpNoExc)() = {};
public:
- Component(celix_bundle_context_t *context, const std::string &name);
+ Component(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, const std::string &name);
~Component() override;
/**
@@ -83,14 +96,14 @@ namespace celix { namespace dm {
* Will use new(nothrow) if exceptions are disabled.
* @return newly created DM Component or nullptr
*/
- static Component<T>* create(celix_bundle_context_t*, const std::string &name);
+ static Component<T>* create(celix_bundle_context_t*, celix_dependency_manager_t* cDepMan, const std::string &name);
/**
* Creates a Component using the provided bundle context.
* Will use new(nothrow) if exceptions are disabled.
* @return newly created DM Component or nullptr
*/
- static Component<T>* create(celix_bundle_context_t*);
+ static Component<T>* create(celix_bundle_context_t*, celix_dependency_manager_t* cDepMan);
/**
* Whether the component is valid. Invalid component can occurs when no new components can be created and
@@ -243,6 +256,14 @@ namespace celix { namespace dm {
* @return the DM Component reference for chaining (fluent API)
*/
Component<T>& removeCallbacks();
+
+ /**
+ * 'Build' the component.
+ * build all the inactive service dependencies.
+ *
+ * Inactive service dependencies are service dependencies where the `build()` is not yet called.
+ */
+ Component<T>& build();
};
}}
diff --git a/libs/framework/include/celix/dm/Component_Impl.h b/libs/framework/include/celix/dm/Component_Impl.h
index 484c4d2..37110fa 100644
--- a/libs/framework/include/celix/dm/Component_Impl.h
+++ b/libs/framework/include/celix/dm/Component_Impl.h
@@ -29,31 +29,55 @@
using namespace celix::dm;
-template<class T>
-Component<T>::Component(celix_bundle_context_t *context, const std::string &name) : BaseComponent(context, name) {}
+inline void BaseComponent::runBuild() {
+ if (context == nullptr || cDepMan == nullptr) {
+ return;
+ }
-template<class T>
-Component<T>::~Component() {
- this->dependencies.clear();
-}
+ for (auto& provideInfo : inactiveProvidedServices) {
+ std::string& serviceName = std::get<0>(provideInfo);
+ std::string& serviceVersion = std::get<1>(provideInfo);
+ Properties& props = std::get<2>(provideInfo);
+ bool isCppService = std::get<3>(provideInfo);
+ void* intfPtr = std::get<4>(provideInfo);
-template<class T>
-template<class I>
-Component<T>& Component<T>::addInterfaceWithName(const std::string &serviceName, const std::string &version, const Properties &properties) {
- if (!serviceName.empty()) {
//setup c properties
celix_properties_t *cProperties = properties_create();
- properties_set(cProperties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_CXX_LANGUAGE);
- for (const auto& pair : properties) {
+ properties_set(cProperties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, isCppService ? CELIX_FRAMEWORK_SERVICE_CXX_LANGUAGE : CELIX_FRAMEWORK_SERVICE_C_LANGUAGE);
+ for (const auto& pair : props) {
properties_set(cProperties, pair.first.c_str(), pair.second.c_str());
}
+ const char *cVersion = serviceVersion.empty() ? nullptr : serviceVersion.c_str();
+ celix_dmComponent_addInterface(this->cComponent(), serviceName.c_str(), cVersion, intfPtr, cProperties);
+ }
+ inactiveProvidedServices.clear();
+
+ for (auto &dep : dependencies) {
+ dep->runBuild();
+ }
+
+ bool alreadyAdded = cmpAddedToDepMan.exchange(true);
+ if (!alreadyAdded) {
+ celix_dependencyManager_add(cDepMan, cCmp);
+ }
+}
+
+template<class T>
+inline Component<T>::Component(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, const std::string &name) : BaseComponent(context, cDepMan, name) {}
+
+template<class T>
+inline Component<T>::~Component() = default;
+
+template<class T>
+template<class I>
+inline Component<T>& Component<T>::addInterfaceWithName(const std::string &serviceName, const std::string &version, const Properties &properties) {
+ if (!serviceName.empty()) {
T* cmpPtr = &this->getInstance();
I* intfPtr = static_cast<I*>(cmpPtr); //NOTE T should implement I
+ void* ptr = static_cast<void*>(intfPtr);
- const char *cVersion = version.empty() ? nullptr : version.c_str();
- celix_dmComponent_addInterface(this->cComponent(), serviceName.c_str(), cVersion,
- intfPtr, cProperties);
+ inactiveProvidedServices.emplace_back(serviceName, version, properties, true, ptr);
} else {
std::cerr << "Cannot add interface with a empty name\n";
}
@@ -63,7 +87,7 @@ Component<T>& Component<T>::addInterfaceWithName(const std::string &serviceName,
template<class T>
template<class I>
-Component<T>& Component<T>::addInterface(const std::string &version, const Properties &properties) {
+inline Component<T>& Component<T>::addInterface(const std::string &version, const Properties &properties) {
//get name if not provided
static_assert(std::is_base_of<I,T>::value, "Component T must implement Interface I");
std::string serviceName = typeName<I>();
@@ -76,23 +100,16 @@ Component<T>& Component<T>::addInterface(const std::string &version, const Prope
template<class T>
template<class I>
-Component<T>& Component<T>::addCInterface(const I* svc, const std::string &serviceName, const std::string &version, const Properties &properties) {
- static_assert(std::is_standard_layout<I>::value, "Service I must be an object with a standard layout");
- celix_properties_t *cProperties = properties_create();
- properties_set(cProperties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE);
- for (const auto& pair : properties) {
- properties_set(cProperties, pair.first.c_str(), pair.second.c_str());
- }
-
- const char *cVersion = version.empty() ? nullptr : version.c_str();
- celix_dmComponent_addInterface(this->cComponent(), serviceName.c_str(), cVersion, svc, cProperties);
-
+inline Component<T>& Component<T>::addCInterface(const I* svc, const std::string &serviceName, const std::string &version, const Properties &properties) {
+ const void* constPtr = static_cast<const void*>(svc);
+ void* ptr = const_cast<void*>(constPtr);
+ inactiveProvidedServices.emplace_back(serviceName, version, properties, false, ptr);
return *this;
}
template<class T>
template<class I>
-Component<T>& Component<T>::removeCInterface(const I* svc){
+inline Component<T>& Component<T>::removeCInterface(const I* svc){
static_assert(std::is_standard_layout<I>::value, "Service I must be an object with a standard layout");
celix_dmComponent_removeInterface(this->cComponent(), svc);
return *this;
@@ -100,21 +117,20 @@ Component<T>& Component<T>::removeCInterface(const I* svc){
template<class T>
template<class I>
-ServiceDependency<T,I>& Component<T>::createServiceDependency(const std::string &name) {
- static ServiceDependency<T,I> invalidDep{std::string{}, false};
- auto dep = std::shared_ptr<ServiceDependency<T,I>> {new ServiceDependency<T,I>(name)};
+inline ServiceDependency<T,I>& Component<T>::createServiceDependency(const std::string &name) {
+ static ServiceDependency<T,I> invalidDep{cComponent(), std::string{}, false};
+ auto dep = std::shared_ptr<ServiceDependency<T,I>> {new ServiceDependency<T,I>(cComponent(), name)};
if (dep == nullptr) {
return invalidDep;
}
- this->dependencies.push_back(dep);
- celix_dmComponent_addServiceDependency(cComponent(), dep->cServiceDependency());
+ dependencies.push_back(dep);
dep->setComponentInstance(&getInstance());
return *dep;
}
template<class T>
template<class I>
-Component<T>& Component<T>::remove(ServiceDependency<T,I>& dep) {
+inline Component<T>& Component<T>::remove(ServiceDependency<T,I>& dep) {
celix_component_removeServiceDependency(cComponent(), dep.cServiceDependency());
this->dependencies.erase(std::remove(this->dependencies.begin(), this->dependencies.end(), dep));
return *this;
@@ -122,36 +138,35 @@ Component<T>& Component<T>::remove(ServiceDependency<T,I>& dep) {
template<class T>
template<typename I>
-CServiceDependency<T,I>& Component<T>::createCServiceDependency(const std::string &name) {
- static CServiceDependency<T,I> invalidDep{std::string{}, false};
- auto dep = std::shared_ptr<CServiceDependency<T,I>> {new CServiceDependency<T,I>(name)};
+inline CServiceDependency<T,I>& Component<T>::createCServiceDependency(const std::string &name) {
+ static CServiceDependency<T,I> invalidDep{cComponent(), std::string{}, false};
+ auto dep = std::shared_ptr<CServiceDependency<T,I>> {new CServiceDependency<T,I>(cComponent(), name)};
if (dep == nullptr) {
return invalidDep;
}
- this->dependencies.push_back(dep);
- celix_dmComponent_addServiceDependency(cComponent(), dep->cServiceDependency());
+ dependencies.push_back(dep);
dep->setComponentInstance(&getInstance());
return *dep;
}
template<class T>
template<typename I>
-Component<T>& Component<T>::remove(CServiceDependency<T,I>& dep) {
+inline Component<T>& Component<T>::remove(CServiceDependency<T,I>& dep) {
celix_component_removeServiceDependency(cComponent(), dep.cServiceDependency());
this->dependencies.erase(std::remove(this->dependencies.begin(), this->dependencies.end(), dep));
return *this;
}
template<class T>
-Component<T>* Component<T>::create(celix_bundle_context_t *context) {
+inline Component<T>* Component<T>::create(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan) {
std::string name = typeName<T>();
- return Component<T>::create(context, name);
+ return Component<T>::create(context, cDepMan, name);
}
template<class T>
-Component<T>* Component<T>::create(celix_bundle_context_t *context, const std::string &name) {
- static Component<T> invalid{nullptr, std::string{}};
- Component<T>* cmp = new (std::nothrow) Component<T>(context, name);
+inline Component<T>* Component<T>::create(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, const std::string &name) {
+ static Component<T> invalid{nullptr, nullptr, std::string{}};
+ Component<T>* cmp = new (std::nothrow) Component<T>(context, cDepMan, name);
if (cmp == nullptr) {
cmp = &invalid;
}
@@ -159,12 +174,12 @@ Component<T>* Component<T>::create(celix_bundle_context_t *context, const std::s
}
template<class T>
-bool Component<T>::isValid() const {
+inline bool Component<T>::isValid() const {
return this->bundleContext() != nullptr;
}
template<class T>
-T& Component<T>::getInstance() {
+inline T& Component<T>::getInstance() {
if (this->valInstance.size() == 1) {
return valInstance.front();
} else if (this->sharedInstance.get() != nullptr) {
@@ -178,7 +193,7 @@ T& Component<T>::getInstance() {
}
template<class T>
-Component<T>& Component<T>::setInstance(std::shared_ptr<T> inst) {
+inline Component<T>& Component<T>::setInstance(std::shared_ptr<T> inst) {
this->valInstance.clear();
this->instance = std::unique_ptr<T> {nullptr};
this->sharedInstance = std::move(inst);
@@ -186,7 +201,7 @@ Component<T>& Component<T>::setInstance(std::shared_ptr<T> inst) {
}
template<class T>
-Component<T>& Component<T>::setInstance(std::unique_ptr<T>&& inst) {
+inline Component<T>& Component<T>::setInstance(std::unique_ptr<T>&& inst) {
this->valInstance.clear();
this->sharedInstance = std::shared_ptr<T> {nullptr};
this->instance = std::move(inst);
@@ -194,7 +209,7 @@ Component<T>& Component<T>::setInstance(std::unique_ptr<T>&& inst) {
}
template<class T>
-Component<T>& Component<T>::setInstance(T&& inst) {
+inline Component<T>& Component<T>::setInstance(T&& inst) {
this->instance = std::unique_ptr<T> {nullptr};
this->sharedInstance = std::shared_ptr<T> {nullptr};
this->valInstance.clear();
@@ -203,7 +218,7 @@ Component<T>& Component<T>::setInstance(T&& inst) {
}
template<class T>
-Component<T>& Component<T>::setCallbacks(
+inline Component<T>& Component<T>::setCallbacks(
void (T::*init)(),
void (T::*start)(),
void (T::*stop)(),
@@ -257,7 +272,7 @@ Component<T>& Component<T>::setCallbacks(
}
template<class T>
-Component<T>& Component<T>::setCallbacks(
+inline Component<T>& Component<T>::setCallbacks(
int (T::*init)(),
int (T::*start)(),
int (T::*stop)(),
@@ -311,10 +326,16 @@ Component<T>& Component<T>::setCallbacks(
}
template<class T>
-Component<T>& Component<T>::removeCallbacks() {
+inline Component<T>& Component<T>::removeCallbacks() {
celix_dmComponent_setCallbacks(this->cComponent(), nullptr, nullptr, nullptr, nullptr);
return *this;
}
+template<typename T>
+inline Component<T>& Component<T>::build() {
+ runBuild();
+ return *this;
+}
+
diff --git a/libs/framework/include/celix/dm/DependencyManager.h b/libs/framework/include/celix/dm/DependencyManager.h
index 3e8b6c1..3a454cb 100644
--- a/libs/framework/include/celix/dm/DependencyManager.h
+++ b/libs/framework/include/celix/dm/DependencyManager.h
@@ -119,7 +119,7 @@ namespace celix { namespace dm {
}
for (auto it = toBeStartedComponents.begin(); it != toBeStartedComponents.end(); ++it) {
- celix_dependencyManager_add(cDepMan, (*it)->cComponent());
+ (*it)->runBuild();
{
std::lock_guard<std::recursive_mutex> lock(componentsMutex);
startedComponents.push_back(std::move(*it));
@@ -150,6 +150,10 @@ namespace celix { namespace dm {
clearStarted.clear();
clearQueued.clear();
}
+
+ std::size_t getNrOfComponents() const {
+ return celix_dependencyManager_nrOfComponents(cDepMan);
+ }
private:
celix_bundle_context_t *context {nullptr};
std::vector<std::unique_ptr<BaseComponent>> queuedComponents {};
diff --git a/libs/framework/include/celix/dm/DependencyManager_Impl.h b/libs/framework/include/celix/dm/DependencyManager_Impl.h
index 716a296..13f2ebd 100644
--- a/libs/framework/include/celix/dm/DependencyManager_Impl.h
+++ b/libs/framework/include/celix/dm/DependencyManager_Impl.h
@@ -20,10 +20,10 @@
using namespace celix::dm;
template<class T>
-Component<T>& DependencyManager::createComponent(std::string name) {
+inline Component<T>& DependencyManager::createComponent(std::string name) {
Component<T>* cmp = name.empty() ?
- Component<T>::create(this->context) :
- Component<T>::create(this->context, name);
+ Component<T>::create(this->context, this->cDepMan) :
+ Component<T>::create(this->context, this->cDepMan, name);
if (cmp->isValid()) {
std::lock_guard<std::recursive_mutex> lock(componentsMutex);
this->queuedComponents.push_back(std::unique_ptr<BaseComponent> {cmp});
@@ -32,16 +32,17 @@ Component<T>& DependencyManager::createComponent(std::string name) {
}
template<class T>
-Component<T>& DependencyManager::createComponent(std::unique_ptr<T>&& rhs, std::string name) {
+inline Component<T>& DependencyManager::createComponent(std::unique_ptr<T>&& rhs, std::string name) {
return this->createComponent<T>(name).setInstance(std::move(rhs));
}
template<class T>
-Component<T>& DependencyManager::createComponent(std::shared_ptr<T> rhs, std::string name) {
+inline Component<T>& DependencyManager::createComponent(std::shared_ptr<T> rhs, std::string name) {
return this->createComponent<T>(name).setInstance(rhs);
}
template<class T>
-Component<T>& DependencyManager::createComponent(T rhs, std::string name) {
+inline Component<T>& DependencyManager::createComponent(T rhs, std::string name) {
return this->createComponent<T>(name).setInstance(std::forward<T>(rhs));
}
+
diff --git a/libs/framework/include/celix/dm/ServiceDependency.h b/libs/framework/include/celix/dm/ServiceDependency.h
index b9163f3..0045720 100644
--- a/libs/framework/include/celix/dm/ServiceDependency.h
+++ b/libs/framework/include/celix/dm/ServiceDependency.h
@@ -42,7 +42,9 @@ namespace celix { namespace dm {
class BaseServiceDependency {
private:
+ celix_dm_component_t* cCmp;
bool valid;
+ std::atomic<bool> depAddedToCmp{false};
protected:
celix_dm_service_dependency_t *cServiceDep {nullptr};
@@ -59,7 +61,7 @@ namespace celix { namespace dm {
}
}
public:
- BaseServiceDependency(bool v) : valid{v} {
+ BaseServiceDependency(celix_dm_component_t* c, bool v) : cCmp{c}, valid{v} {
if (this->valid) {
this->cServiceDep = celix_dmServiceDependency_create();
//NOTE using suspend as default strategy
@@ -83,6 +85,8 @@ namespace celix { namespace dm {
* Returns the C DM service dependency
*/
celix_dm_service_dependency_t *cServiceDependency() const { return cServiceDep; }
+
+ void runBuild();
};
template<class T>
@@ -91,7 +95,7 @@ namespace celix { namespace dm {
protected:
T* componentInstance {nullptr};
public:
- TypedServiceDependency(bool valid) : BaseServiceDependency(valid) {}
+ TypedServiceDependency(celix_dm_component_t* cCmp, bool valid) : BaseServiceDependency(cCmp, valid) {}
~TypedServiceDependency() override = default;
TypedServiceDependency(const TypedServiceDependency&) = delete;
@@ -109,7 +113,7 @@ namespace celix { namespace dm {
class CServiceDependency : public TypedServiceDependency<T> {
using type = I;
public:
- CServiceDependency(const std::string &name, bool valid = true);
+ CServiceDependency(celix_dm_component_t* cCmp, const std::string &name, bool valid = true);
~CServiceDependency() override = default;
CServiceDependency(const CServiceDependency&) = delete;
@@ -200,6 +204,13 @@ namespace celix { namespace dm {
* For C service dependencies 'service.lang=C' will be added.
*/
CServiceDependency<T,I>& setAddLanguageFilter(bool addLang);
+
+ /**
+ * "Build" the service dependency.
+ * A service dependency added to an active component will only become active if the build is called
+ * @return
+ */
+ CServiceDependency<T,I>& build();
private:
std::string name {};
std::string filter {};
@@ -219,7 +230,7 @@ namespace celix { namespace dm {
class ServiceDependency : public TypedServiceDependency<T> {
using type = I;
public:
- ServiceDependency(const std::string &name = std::string{}, bool valid = true);
+ ServiceDependency(celix_dm_component_t* cCmp, const std::string &name, bool valid = true);
~ServiceDependency() override = default;
ServiceDependency(const ServiceDependency&) = delete;
@@ -316,6 +327,14 @@ namespace celix { namespace dm {
* Should be called before
*/
ServiceDependency<T,I>& setAddLanguageFilter(bool addLang);
+
+
+ /**
+ * "Build" the service dependency.
+ * A service dependency added to an active component will only become active if the build is called
+ * @return
+ */
+ ServiceDependency<T,I>& build();
private:
bool addCxxLanguageFilter {true};
std::string name {};
diff --git a/libs/framework/include/celix/dm/ServiceDependency_Impl.h b/libs/framework/include/celix/dm/ServiceDependency_Impl.h
index ea4a04a..6229fb6 100644
--- a/libs/framework/include/celix/dm/ServiceDependency_Impl.h
+++ b/libs/framework/include/celix/dm/ServiceDependency_Impl.h
@@ -25,28 +25,35 @@
using namespace celix::dm;
+inline void BaseServiceDependency::runBuild() {
+ bool alreadyAdded = depAddedToCmp.exchange(true);
+ if (!alreadyAdded) {
+ celix_dmComponent_addServiceDependency(cCmp, cServiceDep);
+ }
+}
+
template<class T, typename I>
-CServiceDependency<T,I>::CServiceDependency(const std::string &name, bool valid) : TypedServiceDependency<T>(valid) {
+inline CServiceDependency<T,I>::CServiceDependency(celix_dm_component_t* cCmp, const std::string &name, bool valid) : TypedServiceDependency<T>(cCmp, valid) {
this->name = name;
this->setupService();
}
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setVersionRange(const std::string &serviceVersionRange) {
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setVersionRange(const std::string &serviceVersionRange) {
this->versionRange = serviceVersionRange;
this->setupService();
return *this;
}
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setFilter(const std::string &_filter) {
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setFilter(const std::string &_filter) {
filter = _filter;
this->setupService();
return *this;
}
template<class T, typename I>
-void CServiceDependency<T,I>::setupService() {
+inline void CServiceDependency<T,I>::setupService() {
if (!this->isValid()) {
return;
}
@@ -56,7 +63,7 @@ void CServiceDependency<T,I>::setupService() {
}
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setAddLanguageFilter(bool addLang) {
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setAddLanguageFilter(bool addLang) {
// if (!this->isValid()) {
// *this;
// }
@@ -66,7 +73,7 @@ CServiceDependency<T,I>& CServiceDependency<T,I>::setAddLanguageFilter(bool addL
}
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setRequired(bool req) {
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setRequired(bool req) {
if (!this->isValid()) {
return *this;
}
@@ -75,7 +82,7 @@ CServiceDependency<T,I>& CServiceDependency<T,I>::setRequired(bool req) {
}
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setStrategy(DependencyUpdateStrategy strategy) {
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setStrategy(DependencyUpdateStrategy strategy) {
if (!this->isValid()) {
return *this;
}
@@ -85,7 +92,7 @@ CServiceDependency<T,I>& CServiceDependency<T,I>::setStrategy(DependencyUpdateSt
//set callbacks
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(void (T::*set)(const I* service)) {
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(void (T::*set)(const I* service)) {
this->setCallbacks([this, set](const I* service, [[gnu::unused]] Properties&& properties) {
T *cmp = this->componentInstance;
(cmp->*set)(service);
@@ -94,7 +101,7 @@ CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(void (T::*set)(co
}
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(void (T::*set)(const I* service, Properties&& properties)) {
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(void (T::*set)(const I* service, Properties&& properties)) {
this->setCallbacks([this, set](const I* service, Properties&& properties) {
T *cmp = this->componentInstance;
(cmp->*set)(service, std::move(properties));
@@ -103,7 +110,7 @@ CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(void (T::*set)(co
}
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(std::function<void(const I* service, Properties&& properties)> set) {
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(std::function<void(const I* service, Properties&& properties)> set) {
this->setFp = set;
this->setupCallbacks();
return *this;
@@ -111,7 +118,7 @@ CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(std::function<voi
//add remove callbacks
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(
void (T::*add)(const I* service),
void (T::*remove)(const I* service)) {
this->setCallbacks(
@@ -128,7 +135,7 @@ CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(
}
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(
void (T::*add)(const I* service, Properties&& properties),
void (T::*remove)(const I* service, Properties&& properties)
) {
@@ -146,7 +153,7 @@ CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(
}
template<class T, typename I>
-CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(std::function<void(const I* service, Properties&& properties)> add, std::function<void(const I* service, Properties&& properties)> remove) {
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(std::function<void(const I* service, Properties&& properties)> add, std::function<void(const I* service, Properties&& properties)> remove) {
this->addFp = add;
this->removeFp = remove;
this->setupCallbacks();
@@ -155,7 +162,7 @@ CServiceDependency<T,I>& CServiceDependency<T,I>::setCallbacks(std::function<voi
template<class T, typename I>
-void CServiceDependency<T,I>::setupCallbacks() {
+inline void CServiceDependency<T,I>::setupCallbacks() {
if (!this->isValid()) {
return;
}
@@ -192,7 +199,7 @@ void CServiceDependency<T,I>::setupCallbacks() {
}
template<class T, typename I>
-int CServiceDependency<T,I>::invokeCallback(std::function<void(const I*, Properties&&)> fp, const celix_properties_t *props, const void* service) {
+inline int CServiceDependency<T,I>::invokeCallback(std::function<void(const I*, Properties&&)> fp, const celix_properties_t *props, const void* service) {
Properties properties {};
const char* key {nullptr};
const char* value {nullptr};
@@ -213,8 +220,14 @@ int CServiceDependency<T,I>::invokeCallback(std::function<void(const I*, Propert
return 0;
}
+
template<class T, class I>
-ServiceDependency<T,I>::ServiceDependency(const std::string &name, bool valid) : TypedServiceDependency<T>(valid) {
+inline CServiceDependency<T,I>& CServiceDependency<T,I>::build() {
+ this->callBuildCallback();
+}
+
+template<class T, class I>
+inline ServiceDependency<T,I>::ServiceDependency(celix_dm_component_t* cCmp, const std::string &name, bool valid) : TypedServiceDependency<T>(cCmp, valid) {
if (!name.empty()) {
this->setName(name);
} else {
@@ -223,7 +236,7 @@ ServiceDependency<T,I>::ServiceDependency(const std::string &name, bool valid) :
}
template<class T, class I>
-void ServiceDependency<T,I>::setupService() {
+inline void ServiceDependency<T,I>::setupService() {
if (!this->isValid()) {
return;
}
@@ -276,21 +289,21 @@ void ServiceDependency<T,I>::setupService() {
}
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setName(const std::string &_name) {
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setName(const std::string &_name) {
name = _name;
setupService();
return *this;
}
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setFilter(const std::string &_filter) {
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setFilter(const std::string &_filter) {
filter = _filter;
setupService();
return *this;
}
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setVersionRange(const std::string &_versionRange) {
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setVersionRange(const std::string &_versionRange) {
versionRange = _versionRange;
setupService();
return *this;
@@ -298,7 +311,7 @@ ServiceDependency<T,I>& ServiceDependency<T,I>::setVersionRange(const std::strin
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setAddLanguageFilter(bool addLang) {
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setAddLanguageFilter(bool addLang) {
this->addCxxLanguageFilter = addLang;
setupService();
return *this;
@@ -306,7 +319,7 @@ ServiceDependency<T,I>& ServiceDependency<T,I>::setAddLanguageFilter(bool addLan
//set callbacks
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(void (T::*set)(I* service)) {
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(void (T::*set)(I* service)) {
this->setCallbacks([this, set](I* srv, [[gnu::unused]] Properties&& props) {
T *cmp = this->componentInstance;
(cmp->*set)(srv);
@@ -315,7 +328,7 @@ ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(void (T::*set)(I* s
}
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(void (T::*set)(I* service, Properties&& properties)) {
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(void (T::*set)(I* service, Properties&& properties)) {
this->setCallbacks([this, set](I* srv, Properties&& props) {
T *cmp = this->componentInstance;
(cmp->*set)(srv, std::move(props));
@@ -324,7 +337,7 @@ ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(void (T::*set)(I* s
}
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(std::function<void(I* service, Properties&& properties)> set) {
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(std::function<void(I* service, Properties&& properties)> set) {
this->setFp = set;
this->setupCallbacks();
return *this;
@@ -332,7 +345,7 @@ ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(std::function<void(
//add remove callbacks
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(
void (T::*add)(I* service),
void (T::*remove)(I* service)) {
this->setCallbacks(
@@ -349,7 +362,7 @@ ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(
}
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(
void (T::*add)(I* service, Properties&& properties),
void (T::*remove)(I* service, Properties&& properties)
) {
@@ -367,7 +380,7 @@ ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(
}
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(
std::function<void(I* service, Properties&& properties)> add,
std::function<void(I* service, Properties&& properties)> remove) {
this->addFp = add;
@@ -377,19 +390,19 @@ ServiceDependency<T,I>& ServiceDependency<T,I>::setCallbacks(
}
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setRequired(bool req) {
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setRequired(bool req) {
celix_dmServiceDependency_setRequired(this->cServiceDependency(), req);
return *this;
}
template<class T, class I>
-ServiceDependency<T,I>& ServiceDependency<T,I>::setStrategy(DependencyUpdateStrategy strategy) {
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::setStrategy(DependencyUpdateStrategy strategy) {
this->setDepStrategy(strategy);
return *this;
}
template<class T, class I>
-int ServiceDependency<T,I>::invokeCallback(std::function<void(I*, Properties&&)> fp, const celix_properties_t *props, const void* service) {
+inline int ServiceDependency<T,I>::invokeCallback(std::function<void(I*, Properties&&)> fp, const celix_properties_t *props, const void* service) {
I *svc = (I*)service;
Properties properties {};
@@ -411,7 +424,7 @@ int ServiceDependency<T,I>::invokeCallback(std::function<void(I*, Properties&&)>
}
template<class T, class I>
-void ServiceDependency<T,I>::setupCallbacks() {
+inline void ServiceDependency<T,I>::setupCallbacks() {
if (!this->isValid()) {
return;
}
@@ -447,3 +460,9 @@ void ServiceDependency<T,I>::setupCallbacks() {
opts.removeWithProps = crem;
celix_dmServiceDependency_setCallbacksWithOptions(this->cServiceDependency(), &opts);
}
+
+template<class T, class I>
+inline ServiceDependency<T,I>& ServiceDependency<T,I>::build() {
+ this->runBuild();
+ return *this;
+}