This is an automated email from the ASF dual-hosted git repository.

pnoltes pushed a commit to branch 
pnoltes/feature/update_component_and_pattern_documentation
in repository https://gitbox.apache.org/repos/asf/celix.git

commit b83d6ecaeee0bda587d391ca2af91b582b336bbe
Author: Pepijn Noltes <[email protected]>
AuthorDate: Tue May 17 16:43:08 2022 +0200

    Updates dm cmp state to atomic and refactors dm cmp for testing.
---
 .../benchmark/src/DependencyManagerBenchmark.cc    |   2 +-
 .../gtest/src/DependencyManagerTestSuite.cc        | 503 ++++++++++++---------
 libs/framework/src/dm_component_impl.c             | 121 +++--
 3 files changed, 340 insertions(+), 286 deletions(-)

diff --git a/libs/framework/benchmark/src/DependencyManagerBenchmark.cc 
b/libs/framework/benchmark/src/DependencyManagerBenchmark.cc
index b52a236e..1a43e275 100644
--- a/libs/framework/benchmark/src/DependencyManagerBenchmark.cc
+++ b/libs/framework/benchmark/src/DependencyManagerBenchmark.cc
@@ -86,7 +86,7 @@ static void createAndDestroyComponentTest(benchmark::State& 
state, bool cTest) {
 
             celix_dependencyManager_addAsync(cMan, cmp);
             celix_dependencyManager_wait(cMan);
-            assert(celix_dmComponent_currentState(cmp) == 
DM_CMP_STATE_TRACKING_OPTIONAL);
+            assert(celix_dmComponent_currentState(cmp) == 
CELIX_DM_CMP_STATE_TRACKING_OPTIONAL);
             celix_dependencyManager_removeAllComponents(cMan);
         }
     } else {
diff --git a/libs/framework/gtest/src/DependencyManagerTestSuite.cc 
b/libs/framework/gtest/src/DependencyManagerTestSuite.cc
index a31b2db4..3aee5f41 100644
--- a/libs/framework/gtest/src/DependencyManagerTestSuite.cc
+++ b/libs/framework/gtest/src/DependencyManagerTestSuite.cc
@@ -19,6 +19,7 @@
 
 #include <gtest/gtest.h>
 #include <atomic>
+#include <condition_variable>
 
 #include "celix/dm/DependencyManager.h"
 #include "celix_framework_factory.h"
@@ -53,14 +54,14 @@ public:
 
 TEST_F(DependencyManagerTestSuite, DmCreateComponent) {
     auto *mng = celix_bundleContext_getDependencyManager(ctx);
-    auto *cmp = celix_dmComponent_create(ctx, "test1");
-    celix_dependencyManager_add(mng, cmp);
+    auto *dmCmp = celix_dmComponent_create(ctx, "test1");
+    celix_dependencyManager_add(mng, dmCmp);
 
     ASSERT_EQ(1, celix_dependencyManager_nrOfComponents(mng));
     ASSERT_TRUE(celix_dependencyManager_allComponentsActive(mng));
 
-    cmp = celix_dmComponent_create(ctx, "test2");
-    celix_dependencyManager_add(mng, cmp);
+    dmCmp = celix_dmComponent_create(ctx, "test2");
+    celix_dependencyManager_add(mng, dmCmp);
 
     ASSERT_EQ(2, celix_dependencyManager_nrOfComponents(mng));
     ASSERT_TRUE(celix_dependencyManager_allComponentsActive(mng));
@@ -68,17 +69,17 @@ TEST_F(DependencyManagerTestSuite, DmCreateComponent) {
 
 TEST_F(DependencyManagerTestSuite, DmComponentAddRemove) {
     auto *mng = celix_bundleContext_getDependencyManager(ctx);
-    auto *cmp = celix_dmComponent_create(ctx, "test1");
-    celix_dependencyManager_add(mng, cmp);
+    auto *dmCmp = celix_dmComponent_create(ctx, "test1");
+    celix_dependencyManager_add(mng, dmCmp);
     ASSERT_EQ(1, celix_dependencyManager_nrOfComponents(mng));
 
-    celix_dependencyManager_remove(mng, cmp);
+    celix_dependencyManager_remove(mng, dmCmp);
     ASSERT_EQ(0, celix_dependencyManager_nrOfComponents(mng));
 
-    auto *cmp2 = celix_dmComponent_create(ctx, "test2");
-    auto *cmp3 = celix_dmComponent_create(ctx, "test3");
-    celix_dependencyManager_add(mng, cmp2);
-    celix_dependencyManager_add(mng, cmp3);
+    auto *dmCmp2 = celix_dmComponent_create(ctx, "test2");
+    auto *dmCmp3 = celix_dmComponent_create(ctx, "test3");
+    celix_dependencyManager_add(mng, dmCmp2);
+    celix_dependencyManager_add(mng, dmCmp3);
     ASSERT_EQ(2, celix_dependencyManager_nrOfComponents(mng));
 
     celix_dependencyManager_removeAllComponents(mng);
@@ -88,8 +89,8 @@ TEST_F(DependencyManagerTestSuite, DmComponentAddRemove) {
 
 TEST_F(DependencyManagerTestSuite, DmComponentAddRemoveAsync) {
     auto *mng = celix_bundleContext_getDependencyManager(ctx);
-    auto *cmp1 = celix_dmComponent_create(ctx, "test1");
-    celix_dependencyManager_addAsync(mng, cmp1);
+    auto *dmCmp1 = celix_dmComponent_create(ctx, "test1");
+    celix_dependencyManager_addAsync(mng, dmCmp1);
     celix_dependencyManager_wait(mng);
     EXPECT_EQ(1, celix_dependencyManager_nrOfComponents(mng));
 
@@ -99,7 +100,7 @@ TEST_F(DependencyManagerTestSuite, 
DmComponentAddRemoveAsync) {
         c->fetch_add(1);
     };
 
-    celix_dependencyManager_removeAsync(mng, cmp1, &count, cb);
+    celix_dependencyManager_removeAsync(mng, dmCmp1, &count, cb);
     celix_dependencyManager_wait(mng);
     EXPECT_EQ(0, celix_dependencyManager_nrOfComponents(mng));
     EXPECT_EQ(1, count.load());
@@ -107,10 +108,10 @@ TEST_F(DependencyManagerTestSuite, 
DmComponentAddRemoveAsync) {
 
 TEST_F(DependencyManagerTestSuite, DmComponentRemoveAllAsync) {
     auto *mng = celix_bundleContext_getDependencyManager(ctx);
-    auto *cmp1 = celix_dmComponent_create(ctx, "test1");
-    auto *cmp2 = celix_dmComponent_create(ctx, "test2");
-    celix_dependencyManager_add(mng, cmp1);
-    celix_dependencyManager_add(mng, cmp2);
+    auto *dmCmp1 = celix_dmComponent_create(ctx, "test1");
+    auto *dmCmp2 = celix_dmComponent_create(ctx, "test2");
+    celix_dependencyManager_add(mng, dmCmp1);
+    celix_dependencyManager_add(mng, dmCmp2);
     EXPECT_EQ(2, celix_dependencyManager_nrOfComponents(mng));
 
     std::atomic<std::size_t> count{0};
@@ -125,19 +126,19 @@ TEST_F(DependencyManagerTestSuite, 
DmComponentRemoveAllAsync) {
 
 TEST_F(DependencyManagerTestSuite, DmGetInfo) {
     auto* mng = celix_bundleContext_getDependencyManager(ctx);
-    auto* cmp = celix_dmComponent_create(ctx, "test1");
+    auto* dmCmp = celix_dmComponent_create(ctx, "test1");
 
     void* dummyInterfacePointer = (void*)0x42;
 
     auto* p = celix_properties_create();
     celix_properties_set(p, "key", "value");
-    celix_dmComponent_addInterface(cmp, "test-interface", nullptr, 
dummyInterfacePointer, p);
+    celix_dmComponent_addInterface(dmCmp, "test-interface", nullptr, 
dummyInterfacePointer, p);
 
     auto* dep = celix_dmServiceDependency_create();
     celix_dmServiceDependency_setService(dep, "test-interface", nullptr, 
nullptr);
-    celix_dmComponent_addServiceDependency(cmp, dep);
+    celix_dmComponent_addServiceDependency(dmCmp, dep);
 
-    celix_dependencyManager_add(mng, cmp);
+    celix_dependencyManager_add(mng, dmCmp);
 
     auto* infos = celix_dependencyManager_createInfos(mng);
     ASSERT_EQ(1, celix_arrayList_size(infos));
@@ -153,15 +154,15 @@ TEST_F(DependencyManagerTestSuite, DmGetInfo) {
 
 TEST_F(DependencyManagerTestSuite, TestCheckActive) {
     auto *mng = celix_bundleContext_getDependencyManager(ctx);
-    auto *cmp = celix_dmComponent_create(ctx, "test1");
+    auto *dmCmp = celix_dmComponent_create(ctx, "test1");
 
     auto *dep = celix_dmServiceDependency_create();
     celix_dmServiceDependency_setService(dep, "svcname", nullptr, nullptr);
     celix_dmServiceDependency_setRequired(dep, true);
-    celix_dmComponent_addServiceDependency(cmp, dep); //required dep -> cmp 
not active
+    celix_dmComponent_addServiceDependency(dmCmp, dep); //required dep -> 
dmCmp not active
 
 
-    celix_dependencyManager_add(mng, cmp);
+    celix_dependencyManager_add(mng, dmCmp);
     ASSERT_FALSE(celix_dependencyManager_areComponentsActive(mng));
 }
 
@@ -188,9 +189,9 @@ public:
 TEST_F(DependencyManagerTestSuite, CxxDmGetInfo) {
     celix::dm::DependencyManager mng{ctx};
 
-    auto& cmp = mng.createComponent<Cmp1>();
-    cmp.createProvidedService<TestService>().addProperty("key", "value");
-    
cmp.createServiceDependency<TestService>().setVersionRange("[1,2)").setRequired(true);
+    auto& dmCmp = mng.createComponent<Cmp1>();
+    dmCmp.createProvidedService<TestService>().addProperty("key", "value");
+    
dmCmp.createServiceDependency<TestService>().setVersionRange("[1,2)").setRequired(true);
 
     auto infos = mng.getInfos();
     EXPECT_EQ(infos.size(), 1);
@@ -204,22 +205,22 @@ TEST_F(DependencyManagerTestSuite, CxxDmGetInfo) {
     info = mng.getInfo(); //new info
     ASSERT_EQ(info.components.size(), 1); //build
 
-    auto& cmpInfo = info.components[0];
-    EXPECT_TRUE(!cmpInfo.uuid.empty());
-    EXPECT_EQ(cmpInfo.name, "Cmp1");
-    EXPECT_EQ(cmpInfo.state, "CELIX_DM_CMP_STATE_WAITING_FOR_REQUIRED");
-    EXPECT_FALSE(cmpInfo.isActive);
-    EXPECT_EQ(cmpInfo.nrOfTimesStarted, 0);
-    EXPECT_EQ(cmpInfo.nrOfTimesResumed, 0);
+    auto& dmCmpInfo = info.components[0];
+    EXPECT_TRUE(!dmCmpInfo.uuid.empty());
+    EXPECT_EQ(dmCmpInfo.name, "Cmp1");
+    EXPECT_EQ(dmCmpInfo.state, "WAITING_FOR_REQUIRED");
+    EXPECT_FALSE(dmCmpInfo.isActive);
+    EXPECT_EQ(dmCmpInfo.nrOfTimesStarted, 0);
+    EXPECT_EQ(dmCmpInfo.nrOfTimesResumed, 0);
 
-    ASSERT_EQ(cmpInfo.interfacesInfo.size(), 1);
-    auto& intf = cmpInfo.interfacesInfo[0];
+    ASSERT_EQ(dmCmpInfo.interfacesInfo.size(), 1);
+    auto& intf = dmCmpInfo.interfacesInfo[0];
     EXPECT_EQ(intf.serviceName, "TestService");
-    EXPECT_TRUE(intf.properties.size() > 0);
+    EXPECT_TRUE(!intf.properties.empty());
     EXPECT_NE(intf.properties.find("key"), intf.properties.end());
 
-    ASSERT_EQ(cmpInfo.dependenciesInfo.size(), 1);
-    auto& dep = cmpInfo.dependenciesInfo[0];
+    ASSERT_EQ(dmCmpInfo.dependenciesInfo.size(), 1);
+    auto& dep = dmCmpInfo.dependenciesInfo[0];
     EXPECT_EQ(dep.serviceName, "TestService");
     EXPECT_EQ(dep.isRequired, true);
     EXPECT_EQ(dep.versionRange, "[1,2)");
@@ -231,13 +232,13 @@ TEST_F(DependencyManagerTestSuite, 
OnlyActiveAfterBuildCheck) {
     celix::dm::DependencyManager dm{ctx};
     EXPECT_EQ(0, dm.getNrOfComponents());
 
-    auto& cmp = 
dm.createComponent<TestComponent>(std::make_shared<TestComponent>(), "test1");
+    auto& dmCmp = 
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());
+    EXPECT_TRUE(dmCmp.isValid());
 
-    cmp.build();
-    cmp.build(); //should be ok to call twice
-    EXPECT_EQ(1, dm.getNrOfComponents()); //cmp "build", so active
+    dmCmp.build();
+    dmCmp.build(); //should be ok to call twice
+    EXPECT_EQ(1, dm.getNrOfComponents()); //dmCmp "build", so active
 
     dm.clear();
     dm.clear(); //should be ok to call twice
@@ -248,12 +249,12 @@ TEST_F(DependencyManagerTestSuite, StartDmWillBuildCmp) {
     celix::dm::DependencyManager dm{ctx};
     EXPECT_EQ(0, dm.getNrOfComponents());
 
-    auto& cmp = 
dm.createComponent<TestComponent>(std::make_shared<TestComponent>(), "test1");
+    auto& dmCmp = 
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());
+    EXPECT_TRUE(dmCmp.isValid());
 
     dm.start();
-    EXPECT_EQ(1, dm.getNrOfComponents()); //cmp "build", so active
+    EXPECT_EQ(1, dm.getNrOfComponents()); //dmCmp "build", so active
 
     dm.stop();
     EXPECT_EQ(0, dm.getNrOfComponents()); //dm cleared so no components
@@ -279,21 +280,21 @@ TEST_F(DependencyManagerTestSuite, 
AddSvcProvideAfterBuild) {
     celix::dm::DependencyManager dm{ctx};
     EXPECT_EQ(0, dm.getNrOfComponents());
 
-    auto& cmp = 
dm.createComponent<TestComponent>(std::make_shared<TestComponent>(), "test1");
+    auto& dmCmp = 
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());
+    EXPECT_TRUE(dmCmp.isValid());
 
-    cmp.build();
-    EXPECT_EQ(1, dm.getNrOfComponents()); //cmp "build", so active
+    dmCmp.build();
+    EXPECT_EQ(1, dm.getNrOfComponents()); //dmCmp "build", so active
 
     TestService svc{};
-    cmp.addCInterface(&svc, "TestService");
+    dmCmp.addCInterface(&svc, "TestService");
 
     long svcId = celix_bundleContext_findService(ctx, "TestService");
     EXPECT_EQ(-1, svcId); //not build -> not found
 
-    cmp.build();
-    cmp.build(); //should be ok to call twice
+    dmCmp.build();
+    dmCmp.build(); //should be ok to call twice
     svcId = celix_bundleContext_findService(ctx, "TestService");
     EXPECT_GT(svcId, -1); //(re)build -> found
 
@@ -309,21 +310,21 @@ TEST_F(DependencyManagerTestSuite, BuildSvcProvide) {
     celix::dm::DependencyManager dm{ctx};
     EXPECT_EQ(0, dm.getNrOfComponents());
 
-    auto& cmp = dm.createComponent<Cmp1>(std::make_shared<Cmp1>(), "test2");
+    auto& dmCmp = dm.createComponent<Cmp1>(std::make_shared<Cmp1>(), "test2");
     EXPECT_EQ(0, dm.getNrOfComponents()); //dm not started yet / comp not 
build yet
-    EXPECT_TRUE(cmp.isValid());
+    EXPECT_TRUE(dmCmp.isValid());
 
-    cmp.build();
-    EXPECT_EQ(1, dm.getNrOfComponents()); //cmp "build", so active
+    dmCmp.build();
+    EXPECT_EQ(1, dm.getNrOfComponents()); //dmCmp "build", so active
 
     TestService svc{};
-    cmp.createProvidedCService(&svc, "CTestService").addProperty("key1", 
"val1").addProperty("key2", 3);
+    dmCmp.createProvidedCService(&svc, "CTestService").addProperty("key1", 
"val1").addProperty("key2", 3);
 
     long svcId = celix_bundleContext_findService(ctx, "CTestService");
     EXPECT_EQ(-1, svcId); //not build -> not found
 
-    cmp.build();
-    cmp.build(); //should be ok to call twice
+    dmCmp.build();
+    dmCmp.build(); //should be ok to call twice
     dm.wait();
     svcId = celix_bundleContext_findService(ctx, "CTestService");
     EXPECT_GT(svcId, -1); //(re)build -> found
@@ -336,7 +337,7 @@ TEST_F(DependencyManagerTestSuite, BuildSvcProvide) {
 
     celix::dm::Properties props{};
     props["key1"] = "value";
-    
cmp.createProvidedService<TestService>().setProperties(props).setVersion("1.0.0").build();
+    
dmCmp.createProvidedService<TestService>().setProperties(props).setVersion("1.0.0").build();
 
     opts.serviceName = "TestService";
     opts.filter = "(key1=value)";
@@ -355,16 +356,16 @@ TEST_F(DependencyManagerTestSuite, AddSvcDepAfterBuild) {
     celix::dm::DependencyManager dm{ctx};
     EXPECT_EQ(0, dm.getNrOfComponents());
 
-    auto& cmp = 
dm.createComponent<TestComponent>(std::make_shared<TestComponent>(), "test1");
+    auto& dmCmp = 
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());
+    EXPECT_TRUE(dmCmp.isValid());
 
-    cmp.build();
-    cmp.build(); //should be ok to call twice
-    EXPECT_EQ(1, dm.getNrOfComponents()); //cmp "build", so active
+    dmCmp.build();
+    dmCmp.build(); //should be ok to call twice
+    EXPECT_EQ(1, dm.getNrOfComponents()); //dmCmp "build", so active
 
     std::atomic<int> count{0};
-    auto& dep = cmp.createCServiceDependency<TestService>("TestService")
+    auto& dep = dmCmp.createCServiceDependency<TestService>("TestService")
             .setCallbacks([&count](const TestService*, 
celix::dm::Properties&&) {
                 count++;
             });
@@ -381,13 +382,13 @@ TEST_F(DependencyManagerTestSuite, AddSvcDepAfterBuild) {
     ASSERT_EQ(1, count); //service dep build -> so count is 1;
 
     //create another service dep
-    cmp.createCServiceDependency<TestService>("TestService")
+    dmCmp.createCServiceDependency<TestService>("TestService")
             .setCallbacks([&count](const TestService*, 
celix::dm::Properties&&) {
                 count++;
             });
     ASSERT_EQ(1, count); //new service dep not yet build -> so count still 1
 
-    cmp.build(); //cmp build, which will build svc dep
+    dmCmp.build(); //dmCmp build, which will build svc dep
     ASSERT_EQ(2, count); //new service dep build -> so count is 2
 
     celix_bundleContext_unregisterService(ctx, svcId);
@@ -398,28 +399,28 @@ TEST_F(DependencyManagerTestSuite, 
InCompleteBuildShouldNotLeak) {
     celix::dm::DependencyManager dm{ctx};
     dm.createComponent<TestComponent>(std::make_shared<TestComponent>(), 
"test1"); //NOTE NOT BUILD
 
-    auto& cmp2 = dm.createComponent<Cmp1>(std::make_shared<Cmp1>(), 
"test2").build(); //NOTE BUILD
-    
cmp2.createCServiceDependency<TestService>("TestService").setFilter("(key=value");
 //note not build
-    
cmp2.createServiceDependency<TestService>().setFilter("(key=value)").setName("alternative
 name"); //note not build
+    auto& dmCmp2 = dm.createComponent<Cmp1>(std::make_shared<Cmp1>(), 
"test2").build(); //NOTE BUILD
+    
dmCmp2.createCServiceDependency<TestService>("TestService").setFilter("(key=value");
 //note not build
+    
dmCmp2.createServiceDependency<TestService>().setFilter("(key=value)").setName("alternative
 name"); //note not build
 
     TestService svc{};
-    cmp2.createProvidedCService(&svc, "CTestService").addProperty("key1", 
"val1"); //note not build
-    cmp2.createProvidedService<TestService>().setVersion("1.0.0"); //note not 
build
+    dmCmp2.createProvidedCService(&svc, "CTestService").addProperty("key1", 
"val1"); //note not build
+    dmCmp2.createProvidedService<TestService>().setVersion("1.0.0"); //note 
not build
 }
 
 
 TEST_F(DependencyManagerTestSuite, RemoveAndClear) {
     celix::dm::DependencyManager dm{ctx};
-    auto& cmp1 = 
dm.createComponent<TestComponent>(std::make_shared<TestComponent>()).build();
-    auto& cmp2 = 
dm.createComponent<TestComponent>(std::make_shared<TestComponent>()).build();
+    auto& dmCmp1 = 
dm.createComponent<TestComponent>(std::make_shared<TestComponent>()).build();
+    auto& dmCmp2 = 
dm.createComponent<TestComponent>(std::make_shared<TestComponent>()).build();
     
dm.createComponent<TestComponent>(std::make_shared<TestComponent>()).build();
-    auto& cmp4 = 
dm.createComponent<TestComponent>(std::make_shared<TestComponent>());
+    auto& dmCmp4 = 
dm.createComponent<TestComponent>(std::make_shared<TestComponent>());
     dm.wait();
 
-    dm.destroyComponent(cmp1);
-    bool removed = dm.removeComponent(cmp2.getUUID());
+    dm.destroyComponent(dmCmp1);
+    bool removed = dm.removeComponent(dmCmp2.getUUID());
     EXPECT_TRUE(removed);
-    removed = dm.removeComponentAsync(cmp4.getUUID());
+    removed = dm.removeComponentAsync(dmCmp4.getUUID());
     EXPECT_TRUE(removed);
     dm.clear();
 }
@@ -465,13 +466,13 @@ TEST_F(DependencyManagerTestSuite, 
RequiredDepsAreInjectedDuringStartStop) {
     };
 
     celix::dm::DependencyManager dm{ctx};
-    auto& cmp = dm.createComponent<LifecycleComponent>()
+    auto& dmCmp = dm.createComponent<LifecycleComponent>()
             .setCallbacks(nullptr, &LifecycleComponent::start, 
&LifecycleComponent::stop, nullptr);
-    cmp.createServiceDependency<TestService>()
+    dmCmp.createServiceDependency<TestService>()
             .setRequired(true)
             .setCallbacks(&LifecycleComponent::setService)
             .setCallbacks(&LifecycleComponent::addService, 
&LifecycleComponent::remService);
-    cmp.build();
+    dmCmp.build();
 
     TestService svc;
     std::string svcName = celix::typeName<TestService>();
@@ -482,124 +483,190 @@ TEST_F(DependencyManagerTestSuite, 
RequiredDepsAreInjectedDuringStartStop) {
     long svcId = 
celix_bundleContext_registerServiceWithOptions(dm.bundleContext(), &opts);
     EXPECT_GE(svcId, 0);
 
-    EXPECT_EQ(cmp.getState(), ComponentState::TRACKING_OPTIONAL);
+    EXPECT_EQ(dmCmp.getState(), ComponentState::TRACKING_OPTIONAL);
     celix_bundleContext_unregisterService(dm.bundleContext(), svcId);
 }
 
+TEST_F(DependencyManagerTestSuite, 
RemoveOwnDependencyShouldNotLeadToDoubleStop) {
+    class LifecycleComponent : public TestService {
+    public:
+        void start() {
+            startCount.fetch_add(1);
+        }
+
+        void stop() {
+            stopCount.fetch_add(1);
+        }
+
+        int getStartCount() const { return startCount.load(); }
+
+        int getStopCount() const { return stopCount.load(); }
+    private:
+        std::atomic<int> startCount{0};
+        std::atomic<int> stopCount{0};
+    };
+
+    celix::dm::DependencyManager dm{ctx};
+    auto lifecycleCmp = std::make_shared<LifecycleComponent>();
+    auto& dmCmp = dm.createComponent<LifecycleComponent>(lifecycleCmp)
+            .setCallbacks(nullptr, &LifecycleComponent::start, 
&LifecycleComponent::stop, nullptr);
+    dmCmp.createProvidedService<TestService>();
+    dmCmp.createServiceDependency<TestService>()
+            .setRequired(true);
+    dmCmp.build();
+
+    using celix::dm::ComponentState;
+    EXPECT_EQ(dmCmp.getState(), ComponentState::WAITING_FOR_REQUIRED);
+
+    TestService svc{};
+    long svcId = celix_bundleContext_registerService(ctx, &svc, "TestService", 
nullptr);
+    celix_bundleContext_waitForEvents(ctx);
+
+    EXPECT_EQ(dmCmp.getState(), ComponentState::TRACKING_OPTIONAL);
+    EXPECT_EQ(lifecycleCmp->getStartCount(), 1);
+
+    celix_bundleContext_unregisterService(ctx, svcId); //removes req dep, but 
cmp can be depend on own dep
+
+    EXPECT_EQ(dmCmp.getState(), ComponentState::TRACKING_OPTIONAL);
+    EXPECT_EQ(lifecycleCmp->getStopCount(), 0);
+
+    //add additional req dep -> stop component -> unregister TestService -> 
rem own TestService dep
+    dmCmp.createServiceDependency<TestService>("DummyName")
+            .setRequired(true)
+            .buildAsync();
+
+    celix_bundleContext_waitForEvents(ctx);
+    EXPECT_EQ(dmCmp.getState(), 
ComponentState::INSTANTIATED_AND_WAITING_FOR_REQUIRED);
+    EXPECT_EQ(lifecycleCmp->getStopCount(), 1);
+}
+
+
 TEST_F(DependencyManagerTestSuite, 
IntermediaStatesDuringInitDeinitStartingAndStopping) {
     class LifecycleComponent {
     public:
-        enum class InMethod {
-            NO_METHOD,
-            INIT,
-            DEINIT,
-            START,
-            STOP
+        enum class LifecycleMethod {
+            None =      0,
+            Init =      1,
+            Start =     2,
+            Stop =      3,
+            Deinit =    4,
         };
 
         void init() {
             std::cout << "in init callback\n";
-            std::unique_lock<std::mutex> lck{mutex};
-            inMethod = InMethod::INIT;
-            cond.notify_all();
-            cond.wait_for(lck, std::chrono::seconds{1});
-            inMethod = InMethod::NO_METHOD;
+            setStateAndWaitToContinue(LifecycleMethod::Init);
         }
 
         void deinit() {
             std::cout << "in deinit callback\n";
-            std::unique_lock<std::mutex> lck{mutex};
-            inMethod = InMethod::DEINIT;
-            cond.notify_all();
-            cond.wait_for(lck, std::chrono::seconds{1});
-            inMethod = InMethod::NO_METHOD;
+            setStateAndWaitToContinue(LifecycleMethod::Deinit);
         }
 
         void start() {
             std::cout << "in start callback\n";
-            std::unique_lock<std::mutex> lck{mutex};
-            inMethod = InMethod::START;
-            cond.notify_all();
-            cond.wait_for(lck, std::chrono::seconds{1});
-            inMethod = InMethod::NO_METHOD;
+            setStateAndWaitToContinue(LifecycleMethod::Start);
         }
 
         void stop() {
             std::cout << "in stop callback\n";
-            std::unique_lock<std::mutex> lck{mutex};
-            inMethod = InMethod::STOP;
+            setStateAndWaitToContinue(LifecycleMethod::Stop);
+        }
+
+        void setStayInMethod(LifecycleMethod m) {
+            std::lock_guard<std::mutex> lck{mutex};
+            stayInMethod = m;
             cond.notify_all();
-            cond.wait_for(lck, std::chrono::seconds{1});
-            inMethod = InMethod::NO_METHOD;
         }
 
-        void waitFor(InMethod s) {
+        void waitUntilInMethod(LifecycleMethod m) {
             std::unique_lock<std::mutex> lck{mutex};
-            cond.wait_for(lck, std::chrono::seconds{1}, [&]{return inMethod == 
s;});
+            cond.wait_for(lck, std::chrono::seconds{5}, [&]{ return 
currentMethod == m; });
         }
-
-        void cont() {
-            std::lock_guard<std::mutex> lck{mutex};
+    private:
+        void setStateAndWaitToContinue(LifecycleMethod m) {
+            std::unique_lock<std::mutex> lck{mutex};
+            currentMethod = m;
+            cond.notify_all();
+            cond.wait_for(lck, std::chrono::seconds{5}, [&] { return 
currentMethod != stayInMethod; });
+            currentMethod = LifecycleMethod::None;
             cond.notify_all();
         }
 
-    private:
         std::mutex mutex{};
         std::condition_variable cond{};
-        InMethod inMethod = InMethod::NO_METHOD;
+        LifecycleMethod stayInMethod = LifecycleMethod::None;
+        LifecycleMethod currentMethod = LifecycleMethod::None;
     };
+    using LifecycleMethod = LifecycleComponent::LifecycleMethod;
+
 
     celix::dm::DependencyManager dm{ctx};
     auto lifecycleCmp = std::make_shared<LifecycleComponent>();
-    auto& cmp = dm.createComponent<LifecycleComponent>(lifecycleCmp)
+    lifecycleCmp->setStayInMethod(LifecycleMethod::Init);
+    auto& dmCmp = dm.createComponent<LifecycleComponent>(lifecycleCmp)
             .setCallbacks(&LifecycleComponent::init, 
&LifecycleComponent::start, &LifecycleComponent::stop, 
&LifecycleComponent::deinit);
-    cmp.createServiceDependency<TestService>()
+    dmCmp.createServiceDependency<TestService>()
+            .setStrategy(celix::dm::DependencyUpdateStrategy::suspend)
+            .setCallbacks([](std::shared_ptr<TestService> /*service*/, const 
std::shared_ptr<const celix::Properties>& /*properties*/){ std::cout << "Dummy 
set for svc callback\n"; })
             .setRequired(false);
-    cmp.build();
+    dmCmp.createServiceDependency<TestService>("RequiredTestService")
+            .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
+            .setRequired(true);
+    dmCmp.buildAsync();
+
+    TestService reqSvc{};
+    long reqSvcId = celix_bundleContext_registerServiceAsync(ctx, &reqSvc, 
"RequiredTestService", nullptr);
+    EXPECT_GE(reqSvcId, 0);
 
     using celix::dm::ComponentState;
-    lifecycleCmp->waitFor(LifecycleComponent::InMethod::INIT);
-    EXPECT_EQ(cmp.getState(), ComponentState::INITIALIZING);
-    lifecycleCmp->cont();
+    lifecycleCmp->waitUntilInMethod(LifecycleMethod::Init);
+    EXPECT_EQ(dmCmp.getState(), ComponentState::INITIALIZING);
 
-    lifecycleCmp->waitFor(LifecycleComponent::InMethod::START);
-    EXPECT_EQ(cmp.getState(), ComponentState::STARTING);
-    lifecycleCmp->cont();
+    lifecycleCmp->setStayInMethod(LifecycleMethod::Start);
+    lifecycleCmp->waitUntilInMethod(LifecycleMethod::Start);
+    EXPECT_EQ(dmCmp.getState(), ComponentState::STARTING);
 
-    lifecycleCmp->waitFor(LifecycleComponent::InMethod::START);
-    EXPECT_EQ(cmp.getState(), ComponentState::STARTING);
-    lifecycleCmp->cont();
+    lifecycleCmp->setStayInMethod(LifecycleMethod::None);
+    lifecycleCmp->waitUntilInMethod(LifecycleMethod::None);
 
     //Adding service should lead to a suspend/resume (stop/start)
+
+    lifecycleCmp->setStayInMethod(LifecycleMethod::Stop);
     TestService svc;
     std::string svcName = celix::typeName<TestService>();
     celix_service_registration_options opts{};
     opts.svc = &svc;
     opts.serviceName = svcName.c_str();
-    long svcId = 
celix_bundleContext_registerServiceWithOptions(dm.bundleContext(), &opts);
-    EXPECT_GE(svcId, 0);
+    long optionalSvcId = 
celix_bundleContext_registerServiceWithOptionsAsync(dm.bundleContext(), &opts);
+    EXPECT_GE(optionalSvcId, 0);
 
-    lifecycleCmp->waitFor(LifecycleComponent::InMethod::STOP);
-    EXPECT_EQ(cmp.getState(), ComponentState::SUSPENDING);
-    lifecycleCmp->cont();
+    lifecycleCmp->waitUntilInMethod(LifecycleMethod::Stop);
+    EXPECT_EQ(dmCmp.getState(), ComponentState::SUSPENDING);
 
-    //svc will be injected
+    //svc will be injected -> component will resume
+    lifecycleCmp->setStayInMethod(LifecycleMethod::Start);
+    lifecycleCmp->waitUntilInMethod(LifecycleMethod::Start);
+    EXPECT_EQ(dmCmp.getState(), ComponentState::RESUMING);
 
-    lifecycleCmp->waitFor(LifecycleComponent::InMethod::START);
-    EXPECT_EQ(cmp.getState(), ComponentState::RESUMING);
-    lifecycleCmp->cont();
 
-    //Adding a required svc should lead to 
INSTANTIATED_AND_WAITING_FOR_REQUIRED
-    cmp.createServiceDependency<TestService>()
-            .setFilter("(non-existing=*)")
-            .setRequired(true)
-            .build();
 
-    lifecycleCmp->waitFor(LifecycleComponent::InMethod::STOP);
-    EXPECT_EQ(cmp.getState(), ComponentState::STOPPING);
-    lifecycleCmp->cont();
+    //Remove required svc so that component stops
+    lifecycleCmp->setStayInMethod(LifecycleMethod::Stop);
+    celix_bundleContext_unregisterServiceAsync(ctx, reqSvcId, nullptr, 
nullptr);
+    lifecycleCmp->waitUntilInMethod(LifecycleMethod::Stop);
+    EXPECT_EQ(dmCmp.getState(), ComponentState::STOPPING);
 
-    celix_bundleContext_unregisterService(dm.bundleContext(), svcId);
+    lifecycleCmp->setStayInMethod(LifecycleMethod::None);
+    lifecycleCmp->waitUntilInMethod(LifecycleMethod::None);
+
+    //Disable component should deinit the component
+    lifecycleCmp->setStayInMethod(LifecycleMethod::Deinit);
+    dm.removeComponentAsync(dmCmp.getUUID());
+    lifecycleCmp->waitUntilInMethod(LifecycleMethod::Deinit);
+    EXPECT_EQ(dmCmp.getState(), ComponentState::DEINITIALIZING);
+
+    lifecycleCmp->setStayInMethod(LifecycleMethod::None);
+    celix_bundleContext_unregisterService(dm.bundleContext(), optionalSvcId);
 }
 
 TEST_F(DependencyManagerTestSuite, DepsAreInjectedAsSharedPointers) {
@@ -645,13 +712,13 @@ TEST_F(DependencyManagerTestSuite, 
DepsAreInjectedAsSharedPointers) {
     };
 
     celix::dm::DependencyManager dm{ctx};
-    auto& cmp = dm.createComponent<LifecycleComponent>()
+    auto& dmCmp = dm.createComponent<LifecycleComponent>()
             .setCallbacks(nullptr, &LifecycleComponent::start, 
&LifecycleComponent::stop, nullptr);
-    cmp.createServiceDependency<TestService>()
+    dmCmp.createServiceDependency<TestService>()
             .setRequired(true)
             .setCallbacks(&LifecycleComponent::setService)
             .setCallbacks(&LifecycleComponent::addService, 
&LifecycleComponent::remService);
-    cmp.build();
+    dmCmp.build();
 
     TestService svc;
     std::string svcName = celix::typeName<TestService>();
@@ -662,7 +729,7 @@ TEST_F(DependencyManagerTestSuite, 
DepsAreInjectedAsSharedPointers) {
     long svcId = 
celix_bundleContext_registerServiceWithOptions(dm.bundleContext(), &opts);
     EXPECT_GE(svcId, 0);
 
-    EXPECT_EQ(cmp.getState(), ComponentState::TRACKING_OPTIONAL);
+    EXPECT_EQ(dmCmp.getState(), ComponentState::TRACKING_OPTIONAL);
     celix_bundleContext_unregisterService(dm.bundleContext(), svcId);
 }
 
@@ -707,13 +774,13 @@ TEST_F(DependencyManagerTestSuite, 
DepsNoPropsAreInjectedAsSharedPointers) {
     };
 
     celix::dm::DependencyManager dm{ctx};
-    auto& cmp = dm.createComponent<LifecycleComponent>()
+    auto& dmCmp = dm.createComponent<LifecycleComponent>()
             .setCallbacks(nullptr, &LifecycleComponent::start, 
&LifecycleComponent::stop, nullptr);
-    cmp.createServiceDependency<TestService>()
+    dmCmp.createServiceDependency<TestService>()
             .setRequired(true)
             .setCallbacks(&LifecycleComponent::setService)
             .setCallbacks(&LifecycleComponent::addService, 
&LifecycleComponent::remService);
-    cmp.build();
+    dmCmp.build();
 
     TestService svc;
     std::string svcName = celix::typeName<TestService>();
@@ -724,7 +791,7 @@ TEST_F(DependencyManagerTestSuite, 
DepsNoPropsAreInjectedAsSharedPointers) {
     long svcId = 
celix_bundleContext_registerServiceWithOptions(dm.bundleContext(), &opts);
     EXPECT_GE(svcId, 0);
 
-    EXPECT_EQ(cmp.getState(), ComponentState::TRACKING_OPTIONAL);
+    EXPECT_EQ(dmCmp.getState(), ComponentState::TRACKING_OPTIONAL);
     celix_bundleContext_unregisterService(dm.bundleContext(), svcId);
 }
 
@@ -756,22 +823,22 @@ TEST_F(DependencyManagerTestSuite, 
UnneededSuspendIsPrevented) {
     };
 
     celix::dm::DependencyManager dm{ctx};
-    //cmp1 has lifecycle callbacks, but not set or add/rem callbacks for the 
service dependency -> should not trigger suspend
-    auto& cmp1 = dm.createComponent<CounterComponent>("CounterCmp1")
+    //dmCmp1 has lifecycle callbacks, but not set or add/rem callbacks for the 
service dependency -> should not trigger suspend
+    auto& dmCmp1 = dm.createComponent<CounterComponent>("CounterCmp1")
             .setCallbacks(nullptr, &CounterComponent::start, 
&CounterComponent::stop, nullptr);
-    cmp1.createServiceDependency<TestService>();
-    cmp1.build();
+    dmCmp1.createServiceDependency<TestService>();
+    dmCmp1.build();
 
-    //cmp2 has lifecycle callbacks and set, add/rem callbacks for the service 
dependency -> should trigger suspend 2x
-    auto& cmp2 = dm.createComponent<CounterComponent>("CounterCmp2")
+    //dmCmp2 has lifecycle callbacks and set, add/rem callbacks for the 
service dependency -> should trigger suspend 2x
+    auto& dmCmp2 = dm.createComponent<CounterComponent>("CounterCmp2")
             .setCallbacks(nullptr, &CounterComponent::start, 
&CounterComponent::stop, nullptr);
-    cmp2.createServiceDependency<TestService>()
+    dmCmp2.createServiceDependency<TestService>()
             .setCallbacks(&CounterComponent::setService)
             .setCallbacks(&CounterComponent::addService, 
&CounterComponent::remService);
-    cmp2.build();
+    dmCmp2.build();
 
-    EXPECT_EQ(cmp1.getState(), celix::dm::ComponentState::TRACKING_OPTIONAL);
-    EXPECT_EQ(cmp2.getState(), celix::dm::ComponentState::TRACKING_OPTIONAL);
+    EXPECT_EQ(dmCmp1.getState(), celix::dm::ComponentState::TRACKING_OPTIONAL);
+    EXPECT_EQ(dmCmp2.getState(), celix::dm::ComponentState::TRACKING_OPTIONAL);
 
     TestService svc;
     std::string svcName = celix::typeName<TestService>();
@@ -782,21 +849,21 @@ TEST_F(DependencyManagerTestSuite, 
UnneededSuspendIsPrevented) {
     long svcId = 
celix_bundleContext_registerServiceWithOptions(dm.bundleContext(), &opts);
     EXPECT_GE(svcId, 0);
 
-    EXPECT_EQ(cmp1.getInstance().startCount, 1); //only once during creation
-    EXPECT_EQ(cmp1.getInstance().stopCount, 0);
-    EXPECT_EQ(cmp2.getInstance().startCount, 3); //1x creation, 1x suspend for 
set, 1x suspend for add
-    EXPECT_EQ(cmp2.getInstance().stopCount, 2); //1x suspend for set, 1x 
suspend for add
+    EXPECT_EQ(dmCmp1.getInstance().startCount, 1); //only once during creation
+    EXPECT_EQ(dmCmp1.getInstance().stopCount, 0);
+    EXPECT_EQ(dmCmp2.getInstance().startCount, 3); //1x creation, 1x suspend 
for set, 1x suspend for add
+    EXPECT_EQ(dmCmp2.getInstance().stopCount, 2); //1x suspend for set, 1x 
suspend for add
 
-    cmp1.getInstance().startCount = 0;
-    cmp1.getInstance().stopCount = 0;
-    cmp2.getInstance().startCount = 0;
-    cmp2.getInstance().stopCount = 0;
+    dmCmp1.getInstance().startCount = 0;
+    dmCmp1.getInstance().stopCount = 0;
+    dmCmp2.getInstance().startCount = 0;
+    dmCmp2.getInstance().stopCount = 0;
     celix_bundleContext_unregisterService(dm.bundleContext(), svcId);
 
-    EXPECT_EQ(cmp1.getInstance().startCount, 0);
-    EXPECT_EQ(cmp1.getInstance().stopCount, 0);
-    EXPECT_EQ(cmp2.getInstance().startCount, 2); //1x suspend for set nullptr, 
1x suspend for rem
-    EXPECT_EQ(cmp2.getInstance().stopCount, 2); //1x suspend for set nullptr, 
1x suspend for rem
+    EXPECT_EQ(dmCmp1.getInstance().startCount, 0);
+    EXPECT_EQ(dmCmp1.getInstance().stopCount, 0);
+    EXPECT_EQ(dmCmp2.getInstance().startCount, 2); //1x suspend for set 
nullptr, 1x suspend for rem
+    EXPECT_EQ(dmCmp2.getInstance().stopCount, 2); //1x suspend for set 
nullptr, 1x suspend for rem
 }
 
 TEST_F(DependencyManagerTestSuite, ExceptionsInLifecycle) {
@@ -840,43 +907,43 @@ TEST_F(DependencyManagerTestSuite, ExceptionsInLifecycle) 
{
     celix::dm::DependencyManager dm{ctx};
 
     {
-        auto& cmp = 
dm.createComponent(std::make_shared<ExceptionComponent>(ExceptionComponent::LifecycleMethod::INIT),
 "FailAtInitCmp")
+        auto& dmCmp = 
dm.createComponent(std::make_shared<ExceptionComponent>(ExceptionComponent::LifecycleMethod::INIT),
 "FailAtInitCmp")
                 .setCallbacks(&ExceptionComponent::init, 
&ExceptionComponent::start, &ExceptionComponent::stop, 
&ExceptionComponent::deinit);
-        EXPECT_EQ(cmp.getState(), ComponentState::INACTIVE);
-        cmp.build(); //fails at init and should disable
-        EXPECT_EQ(cmp.getState(), ComponentState::INACTIVE);
+        EXPECT_EQ(dmCmp.getState(), ComponentState::INACTIVE);
+        dmCmp.build(); //fails at init and should disable
+        EXPECT_EQ(dmCmp.getState(), ComponentState::INACTIVE);
         dm.clear();
     }
 
     {
-        auto& cmp = 
dm.createComponent(std::make_shared<ExceptionComponent>(ExceptionComponent::LifecycleMethod::START),
 "FailAtStartCmp")
+        auto& dmCmp = 
dm.createComponent(std::make_shared<ExceptionComponent>(ExceptionComponent::LifecycleMethod::START),
 "FailAtStartCmp")
                 .setCallbacks(&ExceptionComponent::init, 
&ExceptionComponent::start, &ExceptionComponent::stop, 
&ExceptionComponent::deinit);
-        EXPECT_EQ(cmp.getState(), ComponentState::INACTIVE);
-        cmp.build(); //fails at init and should disable
-        EXPECT_EQ(cmp.getState(), ComponentState::INACTIVE);
+        EXPECT_EQ(dmCmp.getState(), ComponentState::INACTIVE);
+        dmCmp.build(); //fails at init and should disable
+        EXPECT_EQ(dmCmp.getState(), ComponentState::INACTIVE);
         dm.clear();
     }
 
     {
-        auto& cmp = 
dm.createComponent(std::make_shared<ExceptionComponent>(ExceptionComponent::LifecycleMethod::STOP),
 "FailAtStopCmp")
+        auto& dmCmp = 
dm.createComponent(std::make_shared<ExceptionComponent>(ExceptionComponent::LifecycleMethod::STOP),
 "FailAtStopCmp")
                 .setCallbacks(&ExceptionComponent::init, 
&ExceptionComponent::start, &ExceptionComponent::stop, 
&ExceptionComponent::deinit);
-        EXPECT_EQ(cmp.getState(), ComponentState::INACTIVE);
-        cmp.build();
-        EXPECT_EQ(cmp.getState(), ComponentState::TRACKING_OPTIONAL);
+        EXPECT_EQ(dmCmp.getState(), ComponentState::INACTIVE);
+        dmCmp.build();
+        EXPECT_EQ(dmCmp.getState(), ComponentState::TRACKING_OPTIONAL);
 
         //required service -> should stop, but fails at stop and should become 
inactive (component will disable itself)
-        cmp.createServiceDependency<TestService>().setRequired(true).build();
-        cmp.wait();
-        EXPECT_EQ(cmp.getState(), ComponentState::INACTIVE);
+        dmCmp.createServiceDependency<TestService>().setRequired(true).build();
+        dmCmp.wait();
+        EXPECT_EQ(dmCmp.getState(), ComponentState::INACTIVE);
         dm.clear();
     }
 
     {
-        auto& cmp = 
dm.createComponent(std::make_shared<ExceptionComponent>(ExceptionComponent::LifecycleMethod::DEINIT),
 "FailAtDeinit")
+        auto& dmCmp = 
dm.createComponent(std::make_shared<ExceptionComponent>(ExceptionComponent::LifecycleMethod::DEINIT),
 "FailAtDeinit")
                 .setCallbacks(&ExceptionComponent::init, 
&ExceptionComponent::start, &ExceptionComponent::stop, 
&ExceptionComponent::deinit);
-        EXPECT_EQ(cmp.getState(), ComponentState::INACTIVE);
-        cmp.build();
-        EXPECT_EQ(cmp.getState(), ComponentState::TRACKING_OPTIONAL);
+        EXPECT_EQ(dmCmp.getState(), ComponentState::INACTIVE);
+        dmCmp.build();
+        EXPECT_EQ(dmCmp.getState(), ComponentState::TRACKING_OPTIONAL);
 
         //required service -> should stop, but fails at stop and should become 
inactive (component will disable itself)
         dm.clear(); //dm clear will deinit component and this should fail, but 
not deadlock
@@ -906,31 +973,31 @@ TEST_F(DependencyManagerTestSuite, 
installBundleWithDepManActivator) {
 
 TEST_F(DependencyManagerTestSuite, testStateToString) {
     const char* state = 
celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_INACTIVE);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_INACTIVE");
+    EXPECT_STREQ(state, "INACTIVE");
     state = 
celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_WAITING_FOR_REQUIRED);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_WAITING_FOR_REQUIRED");
+    EXPECT_STREQ(state, "WAITING_FOR_REQUIRED");
     state = celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_INITIALIZING);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_INITIALIZING");
+    EXPECT_STREQ(state, "INITIALIZING");
     state = celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_DEINITIALIZING);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_DEINITIALIZING");
+    EXPECT_STREQ(state, "DEINITIALIZING");
     state = 
celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_INITIALIZED_AND_WAITING_FOR_REQUIRED);
-    EXPECT_STREQ(state, 
"CELIX_DM_CMP_STATE_INITIALIZED_AND_WAITING_FOR_REQUIRED");
+    EXPECT_STREQ(state, "INITIALIZED_AND_WAITING_FOR_REQUIRED");
     state = celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_STARTING);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_STARTING");
+    EXPECT_STREQ(state, "STARTING");
     state = celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_STOPPING);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_STOPPING");
+    EXPECT_STREQ(state, "STOPPING");
     state = 
celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_TRACKING_OPTIONAL);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_TRACKING_OPTIONAL");
+    EXPECT_STREQ(state, "TRACKING_OPTIONAL");
     state = celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_SUSPENDING);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_SUSPENDING");
+    EXPECT_STREQ(state, "SUSPENDING");
     state = celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_SUSPENDED);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_SUSPENDED");
+    EXPECT_STREQ(state, "SUSPENDED");
     state = celix_dmComponent_stateToString(CELIX_DM_CMP_STATE_RESUMING);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_RESUMING");
+    EXPECT_STREQ(state, "RESUMING");
     state = celix_dmComponent_stateToString((celix_dm_component_state_enum)0);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_INACTIVE");
+    EXPECT_STREQ(state, "INACTIVE");
     state = celix_dmComponent_stateToString((celix_dm_component_state_enum)16);
-    EXPECT_STREQ(state, "CELIX_DM_CMP_STATE_INACTIVE");
+    EXPECT_STREQ(state, "INACTIVE");
 }
 
 #if __cplusplus >= 201703L //C++17 or higher
@@ -944,10 +1011,10 @@ public:
 TEST_F(DependencyManagerTestSuite, ProvideInterfaceWithStaticInfo) {
     class TestComponent : public TestInterfaceWithStaticInfo {};
     celix::dm::DependencyManager dm{ctx};
-    auto& cmp = dm.createComponent<TestComponent>();
-    cmp.createProvidedService<TestInterfaceWithStaticInfo>();
-    cmp.build();
-    EXPECT_EQ(cmp.getState(), celix::dm::ComponentState::TRACKING_OPTIONAL);
+    auto& dmCmp = dm.createComponent<TestComponent>();
+    dmCmp.createProvidedService<TestInterfaceWithStaticInfo>();
+    dmCmp.build();
+    EXPECT_EQ(dmCmp.getState(), celix::dm::ComponentState::TRACKING_OPTIONAL);
 
     auto info = dm.getInfo();
     EXPECT_EQ(info.components[0].interfacesInfo[0].serviceName, "TestName");
@@ -960,10 +1027,10 @@ TEST_F(DependencyManagerTestSuite, 
ProvideInterfaceWithStaticInfo) {
 TEST_F(DependencyManagerTestSuite, CreateInterfaceWithStaticInfo) {
     class TestComponent : public TestInterfaceWithStaticInfo {};
     celix::dm::DependencyManager dm{ctx};
-    auto& cmp = dm.createComponent<TestComponent>();
-    cmp.addInterface<TestInterfaceWithStaticInfo>();
-    cmp.build();
-    EXPECT_EQ(cmp.getState(), celix::dm::ComponentState::TRACKING_OPTIONAL);
+    auto& dmCmp = dm.createComponent<TestComponent>();
+    dmCmp.addInterface<TestInterfaceWithStaticInfo>();
+    dmCmp.build();
+    EXPECT_EQ(dmCmp.getState(), celix::dm::ComponentState::TRACKING_OPTIONAL);
 
     auto info = dm.getInfo();
     EXPECT_EQ(info.components[0].interfacesInfo[0].serviceName, "TestName");
diff --git a/libs/framework/src/dm_component_impl.c 
b/libs/framework/src/dm_component_impl.c
index ca213435..eba1e022 100644
--- a/libs/framework/src/dm_component_impl.c
+++ b/libs/framework/src/dm_component_impl.c
@@ -34,7 +34,6 @@ struct celix_dm_component_struct {
     char name[DM_COMPONENT_MAX_NAME_LENGTH];
 
     celix_bundle_context_t* context;
-    bool setCLanguageProperty;
     void* implementation;
 
     celix_dm_cmp_lifecycle_fpt callbackInit;
@@ -42,6 +41,8 @@ struct celix_dm_component_struct {
     celix_dm_cmp_lifecycle_fpt callbackStop;
     celix_dm_cmp_lifecycle_fpt callbackDeinit;
 
+    celix_dm_component_state_t state; //atomic
+
     celix_thread_mutex_t mutex; //protects below
     celix_array_list_t* providedInterfaces; //type = dm_interface_t*
     celix_array_list_t* dependencies; //type = celix_dm_service_dependency_t*
@@ -51,8 +52,6 @@ struct celix_dm_component_struct {
      */
     celix_array_list_t* removedDependencies; //type = 
celix_dm_service_dependency_t*
 
-    celix_dm_component_state_t state;
-
     size_t nrOfTimesStarted;
     size_t nrOfTimesResumed;
 
@@ -90,7 +89,8 @@ static celix_status_t 
celix_dmComponent_disableDependencies(celix_dm_component_t
 static bool celix_dmComponent_isDisabled(celix_dm_component_t *component);
 static void celix_dmComponent_cleanupRemovedDependencies(celix_dm_component_t* 
component);
 static bool celix_dmComponent_isActiveInternal(celix_dm_component_t 
*component);
-
+static void celix_dmComponent_setCurrentState(celix_dm_component_t* cmp, 
celix_dm_component_state_t s);
+static void celix_dmComponent_logTransition(celix_dm_component_t* cmp, 
celix_dm_component_state_t currentState, celix_dm_component_state_t 
desiredState);
 
 celix_dm_component_t* celix_dmComponent_create(bundle_context_t *context, 
const char* name) {
     return celix_dmComponent_createWithUUID(context, name, NULL);
@@ -131,13 +131,13 @@ celix_dm_component_t* 
celix_dmComponent_createWithUUID(bundle_context_t *context
     component->callbackStop = NULL;
     component->callbackDeinit = NULL;
     component->state = CELIX_DM_CMP_STATE_INACTIVE;
-    component->setCLanguageProperty = false;
 
     component->providedInterfaces = celix_arrayList_create();
     component->dependencies = celix_arrayList_create();
     component->removedDependencies = celix_arrayList_create();
     celixThreadMutex_create(&component->mutex, NULL);
     component->isEnabled = false;
+    component->inTransition = false;
     return component;
 }
 
@@ -258,7 +258,7 @@ celix_status_t 
celix_dmComponent_addServiceDependency(celix_dm_component_t *comp
 
     celixThreadMutex_lock(&component->mutex);
     arrayList_add(component->dependencies, dep);
-    bool startDep = component->state != CELIX_DM_CMP_STATE_INACTIVE;
+    bool startDep = celix_dmComponent_currentState(component) != 
CELIX_DM_CMP_STATE_INACTIVE;
     if (startDep) {
         celix_dmServiceDependency_enable(dep);
     }
@@ -273,7 +273,7 @@ celix_status_t 
celix_dmComponent_removeServiceDependency(celix_dm_component_t *c
 
     celixThreadMutex_lock(&component->mutex);
     celix_arrayList_remove(component->dependencies, dep);
-    bool disableDependency = component->state != CELIX_DM_CMP_STATE_INACTIVE;
+    bool disableDependency = celix_dmComponent_currentState(component) != 
CELIX_DM_CMP_STATE_INACTIVE;
     if (disableDependency) {
         celix_dmServiceDependency_disable(dep);
     }
@@ -289,12 +289,13 @@ celix_dm_component_state_t 
component_currentState(celix_dm_component_t *cmp) {
     return celix_dmComponent_currentState(cmp);
 }
 
+static void celix_dmComponent_setCurrentState(celix_dm_component_t* cmp, 
celix_dm_component_state_t s) {
+    __atomic_store_n(&cmp->state, s, __ATOMIC_RELEASE);
+}
+
 celix_dm_component_state_t celix_dmComponent_currentState(celix_dm_component_t 
*cmp) {
-    celix_dm_component_state_t state;
-    celixThreadMutex_lock(&cmp->mutex);
-    state = cmp->state;
-    celixThreadMutex_unlock(&cmp->mutex);
-    return state;
+   celix_dm_component_state_t state = __atomic_load_n(&cmp->state, 
__ATOMIC_ACQUIRE);
+   return state;
 }
 
 void* component_getImplementation(celix_dm_component_t *cmp) {
@@ -355,7 +356,7 @@ static celix_status_t 
celix_dmComponent_disable(celix_dm_component_t *component)
  */
 static void celix_dmComponent_disableDirectly(celix_dm_component_t *component) 
{
     component->isEnabled = false;
-    component->state = CELIX_DM_CMP_STATE_INACTIVE;
+    celix_dmComponent_setCurrentState(component, CELIX_DM_CMP_STATE_INACTIVE);
     celix_dmComponent_unregisterServices(component, false);
     celix_dmComponent_disableDependencies(component);
 }
@@ -400,7 +401,7 @@ static bool 
celix_dmComponent_isDisabled(celix_dm_component_t *component) {
     celixThreadMutex_lock(&component->mutex);
     isStopped =
             !component->isEnabled &&
-            component->state == CELIX_DM_CMP_STATE_INACTIVE &&
+            celix_dmComponent_currentState(component) == 
CELIX_DM_CMP_STATE_INACTIVE &&
             celix_dmComponent_areAllDependenciesDisabled(component);
     celixThreadMutex_unlock(&component->mutex);
     return isStopped;
@@ -443,7 +444,7 @@ celix_status_t 
celix_dmComponent_addInterface(celix_dm_component_t *component, c
         interface->properties = properties;
         interface->svcId= -1L;
         celix_arrayList_add(component->providedInterfaces, interface);
-        if (component->state == CELIX_DM_CMP_STATE_TRACKING_OPTIONAL) {
+        if (celix_dmComponent_currentState(component) == 
CELIX_DM_CMP_STATE_TRACKING_OPTIONAL) {
             celix_dmComponent_registerServices(component, false);
         }
         celixThreadMutex_unlock(&component->mutex);
@@ -529,19 +530,15 @@ static celix_status_t 
celix_dmComponent_suspend(celix_dm_component_t *component,
        celix_status_t status = CELIX_SUCCESS;
        if (component->callbackStop != NULL) {
         celixThreadMutex_lock(&component->mutex);
-        component->state = CELIX_DM_CMP_STATE_SUSPENDING;
-        celix_bundleContext_log(component->context, CELIX_LOG_LEVEL_TRACE,
-               "Suspending component %s (uuid=%s)",
-               component->name,
-               component->uuid);
+        celix_dmComponent_logTransition(component, 
celix_dmComponent_currentState(component),
+                                        CELIX_DM_CMP_STATE_SUSPENDING);
+        celix_dmComponent_setCurrentState(component, 
CELIX_DM_CMP_STATE_SUSPENDING);
         celix_dmComponent_unregisterServices(component, false);
                status = component->callbackStop(component->implementation);
         if (status == CELIX_SUCCESS) {
-            component->state = CELIX_DM_CMP_STATE_SUSPENDED;
-            celix_bundleContext_log(component->context, CELIX_LOG_LEVEL_TRACE,
-                                    "Suspended component %s (uuid=%s)",
-                                    component->name,
-                                    component->uuid);
+            celix_dmComponent_logTransition(component, 
celix_dmComponent_currentState(component),
+                                            CELIX_DM_CMP_STATE_SUSPENDED);
+            celix_dmComponent_setCurrentState(component, 
CELIX_DM_CMP_STATE_SUSPENDED);
         } else {
             celix_bundleContext_log(component->context, CELIX_LOG_LEVEL_ERROR,
                                     "Error stopping component %s (uuid=%s) 
using the stop callback. Disabling component.",
@@ -557,21 +554,17 @@ static celix_status_t 
celix_dmComponent_suspend(celix_dm_component_t *component,
 static celix_status_t celix_dmComponent_resume(celix_dm_component_t 
*component, celix_dm_service_dependency_t *dependency) {
        celix_status_t status = CELIX_SUCCESS;
     celixThreadMutex_lock(&component->mutex);
-       if (component->state == CELIX_DM_CMP_STATE_SUSPENDED) {
-        component->state = CELIX_DM_CMP_STATE_RESUMING;
-        celix_bundleContext_log(component->context, CELIX_LOG_LEVEL_TRACE,
-                                "Resuming component %s (uuid=%s)",
-                                component->name,
-                                component->uuid);
+       if (celix_dmComponent_currentState(component) == 
CELIX_DM_CMP_STATE_SUSPENDED) {
+        celix_dmComponent_logTransition(component, 
celix_dmComponent_currentState(component),
+                                        CELIX_DM_CMP_STATE_RESUMING);
+        celix_dmComponent_setCurrentState(component, 
CELIX_DM_CMP_STATE_RESUMING);
         status = component->callbackStart(component->implementation);
         if (status == CELIX_SUCCESS) {
             celix_dmComponent_registerServices(component, false);
             component->nrOfTimesResumed += 1;
-            component->state = CELIX_DM_CMP_STATE_TRACKING_OPTIONAL;
-            celix_bundleContext_log(component->context, CELIX_LOG_LEVEL_TRACE,
-                                    "Resumed component %s (uuid=%s)",
-                                    component->name,
-                                    component->uuid);
+            celix_dmComponent_logTransition(component, 
celix_dmComponent_currentState(component),
+                                            
CELIX_DM_CMP_STATE_TRACKING_OPTIONAL);
+            celix_dmComponent_setCurrentState(component, 
CELIX_DM_CMP_STATE_TRACKING_OPTIONAL);
         } else {
             celix_bundleContext_log(component->context, CELIX_LOG_LEVEL_ERROR,
                                     "Error starting component %s (uuid=%s) 
using the start callback. Disabling component.",
@@ -587,26 +580,15 @@ static celix_status_t 
celix_dmComponent_resume(celix_dm_component_t *component,
 }
 
 static bool celix_dmComponent_needsSuspend(celix_dm_component_t *component, 
const celix_dm_event_t* event) {
-    bool cmpActive = false;
-    celixThreadMutex_lock(&component->mutex);
-    switch (component->state) {
-        case CELIX_DM_CMP_STATE_TRACKING_OPTIONAL:
-            cmpActive = true;
-            break;
-        default: //DM_CMP_STATE_INACTIVE
-            break;
-    }
-    celixThreadMutex_unlock(&component->mutex);
-    if (cmpActive) {
+    if (celix_dmComponent_currentState(component) == 
CELIX_DM_CMP_STATE_TRACKING_OPTIONAL) {
         bool callbackConfigured = event->eventType == CELIX_DM_EVENT_SVC_SET ?
                                   
celix_dmServiceDependency_isSetCallbackConfigured(event->dep) :
                                  /*add or rem*/ 
celix_dmServiceDependency_isAddRemCallbacksConfigured(event->dep);
         dm_service_dependency_strategy_t strategy = 
celix_dmServiceDependency_getStrategy(event->dep);
         bool suspendStrategy = strategy == 
DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND;
         return suspendStrategy && callbackConfigured;
-    } else {
-        return false;
     }
+    return false;
 }
 
 static celix_status_t celix_dmComponent_handleEvent(celix_dm_component_t 
*component, const celix_dm_event_t* event, celix_status_t 
(*setAddOrRemFp)(celix_dm_service_dependency_t *dependency, void* svc, const 
celix_properties_t* props), const char *invokeName) {
@@ -706,12 +688,12 @@ static void 
celix_dmComponent_handleChangeOnEventThread(void *data) {
     celix_dm_component_state_t newState;
     bool transition = false;
     do {
-        oldState = component->state;
+        oldState = celix_dmComponent_currentState(component);
         celix_status_t status = celix_dmComponent_calculateNewState(component, 
oldState, &newState);
         if (status == CELIX_SUCCESS) {
             transition = celix_dmComponent_performTransition(component, 
oldState, newState);
             if (transition) {
-                component->state = newState;
+                celix_dmComponent_setCurrentState(component, newState);
             }
         }
 
@@ -808,13 +790,7 @@ static bool 
celix_dmComponent_performTransition(celix_dm_component_t *component,
     }
     component->inTransition = true;
 
-    celix_bundleContext_log(component->context,
-           CELIX_LOG_LEVEL_TRACE,
-           "performing transition for component '%s' (uuid=%s) from state %s 
to state %s",
-           component->name,
-           component->uuid,
-           celix_dmComponent_stateToString(currentState),
-           celix_dmComponent_stateToString(desiredState));
+    celix_dmComponent_logTransition(component, currentState, desiredState);
 
     celix_status_t status = CELIX_SUCCESS;
     if (currentState == CELIX_DM_CMP_STATE_INACTIVE && desiredState == 
CELIX_DM_CMP_STATE_WAITING_FOR_REQUIRED) {
@@ -1025,7 +1001,8 @@ celix_status_t 
celix_dmComponent_getComponentInfo(celix_dm_component_t *componen
     memcpy(info->name, component->name, DM_COMPONENT_MAX_NAME_LENGTH);
     info->nrOfTimesStarted = component->nrOfTimesStarted;
     info->nrOfTimesResumed = component->nrOfTimesResumed;
-    info->state = 
celix_utils_strdup(celix_dmComponent_stateToString(component->state));
+    celix_dm_component_state_t state = 
celix_dmComponent_currentState(component);
+    info->state = celix_utils_strdup(celix_dmComponent_stateToString(state));
     info->active = celix_dmComponent_isActiveInternal(component);
 
     for (int i = 0; i < celix_arrayList_size(component->dependencies); i += 1) 
{
@@ -1073,19 +1050,18 @@ void 
celix_dmComponent_destroyComponentInfo(dm_component_info_pt info) {
 
 static bool celix_dmComponent_isActiveInternal(celix_dm_component_t 
*component) {
     //precondition: mutex component->mutex taken.
+    celix_dm_component_state_t state = 
celix_dmComponent_currentState(component);
     return
-            component->state == CELIX_DM_CMP_STATE_STARTING ||
-            component->state == CELIX_DM_CMP_STATE_TRACKING_OPTIONAL ||
-            component->state == CELIX_DM_CMP_STATE_SUSPENDING ||
-            component->state == CELIX_DM_CMP_STATE_SUSPENDED ||
-            component->state == CELIX_DM_CMP_STATE_RESUMING ||
-            component->state == CELIX_DM_CMP_STATE_STOPPING;
+            state == CELIX_DM_CMP_STATE_STARTING ||
+            state == CELIX_DM_CMP_STATE_TRACKING_OPTIONAL ||
+            state == CELIX_DM_CMP_STATE_SUSPENDING ||
+            state == CELIX_DM_CMP_STATE_SUSPENDED ||
+            state == CELIX_DM_CMP_STATE_RESUMING ||
+            state == CELIX_DM_CMP_STATE_STOPPING;
 }
 
 bool celix_dmComponent_isActive(celix_dm_component_t *component) {
-    celixThreadMutex_lock(&component->mutex);
     bool isActivate = celix_dmComponent_isActiveInternal(component);
-    celixThreadMutex_unlock(&component->mutex);
     return isActivate;
 }
 
@@ -1115,3 +1091,14 @@ const char* 
celix_dmComponent_stateToString(celix_dm_component_state_t state) {
             return "INACTIVE";
     }
 }
+
+
+static void celix_dmComponent_logTransition(celix_dm_component_t* cmp, 
celix_dm_component_state_t currentState, celix_dm_component_state_t 
desiredState) {
+    celix_bundleContext_log(cmp->context,
+    CELIX_LOG_LEVEL_TRACE,
+        "Component transition from %s -> %s for '%s' (uuid=%s).",
+        celix_dmComponent_stateToString(currentState),
+        celix_dmComponent_stateToString(desiredState),
+        cmp->name,
+        cmp->uuid);
+}
\ No newline at end of file

Reply via email to