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/10/04 18:53:09 UTC

[celix] 03/04: Update bc_useService(s) so that it can be called on the event loop thread

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

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

commit 18770324b219064a3a37a749eb3fabe7b63098e5
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Oct 4 19:29:50 2020 +0200

    Update bc_useService(s) so that it can be called on the event loop thread
---
 .../org.apache.celix.RemoteExample.descriptor      |  2 +-
 .../gtest/src/tst_activator.c                      |  1 +
 .../gtest/src/bundle_context_services_test.cpp     |  4 ++++
 libs/framework/include/celix_bundle_context.h      | 21 ++++++++++++----
 libs/framework/include/service_registry.h          |  2 ++
 libs/framework/src/bundle_context.c                | 28 +++++++++++++++++-----
 libs/framework/src/service_registry.c              | 20 ++++++++++++++++
 7 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor b/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor
index 0558c7f..6cbefb2 100644
--- a/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor
+++ b/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor
@@ -16,4 +16,4 @@ setName2=setName2(#am=handle;P#const=true;t#am=out;*t)N
 setEnum=setEnum(#am=handle;Plenum_example;#am=pre;Lenum_example;)N
 action=action(#am=handle;P)N
 setComplex=setComplex(#am=handle;PLcomplex_input;#am=out;*Lcomplex_output;)N
-createAdditionalRemoteService=createAdditionalRemoteService(#am=handle;P)N
+createAdditionalRemoteService=createAdditionalRemoteService(#am=handle;P)N
\ No newline at end of file
diff --git a/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c b/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c
index e3a8000..0f1cbb9 100644
--- a/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c
+++ b/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c
@@ -315,6 +315,7 @@ static celix_status_t bndStart(struct activator *act, celix_bundle_context_t* ct
     act->testSvc.testCreateRemoteServiceInRemoteCall = testCreateRemoteServiceInRemoteCall;
     act->testSvc.testCreateDestroyComponentWithRemoteService = bndTestCreateDestroyComponentWithRemoteService;
 
+    act->testSvc.testCreateRemoteServiceInRemoteCall = testCreateRemoteServiceInRemoteCall;
 
     //create mutex
     pthread_mutex_init(&act->mutex, NULL);
diff --git a/libs/framework/gtest/src/bundle_context_services_test.cpp b/libs/framework/gtest/src/bundle_context_services_test.cpp
index 9e5335f..f20a449 100644
--- a/libs/framework/gtest/src/bundle_context_services_test.cpp
+++ b/libs/framework/gtest/src/bundle_context_services_test.cpp
@@ -1063,6 +1063,9 @@ TEST_F(CelixBundleContextServicesTests, floodEventLoopTest) {
         EXPECT_GE(id, 0);
         svcIds.push_back(id);
         trackerIds.push_back(celix_bundleContext_trackServicesAsync(ctx, "test", nullptr, nullptr, nullptr));
+
+        //CHECK if celix_bundleContext_isServiceRegistered work
+        EXPECT_FALSE(celix_bundleContext_isServiceRegistered(ctx, id));
     }
 
     {
@@ -1073,6 +1076,7 @@ TEST_F(CelixBundleContextServicesTests, floodEventLoopTest) {
     }
 
     celix_bundleContext_waitForAsyncRegistration(ctx, svcId);
+    EXPECT_TRUE(celix_bundleContext_isServiceRegistered(ctx, svcId));
     long foundId = celix_bundleContext_findService(ctx, "test");
     EXPECT_GE(foundId, 0);
 
diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h
index 060a749..db69378 100644
--- a/libs/framework/include/celix_bundle_context.h
+++ b/libs/framework/include/celix_bundle_context.h
@@ -45,7 +45,8 @@ extern "C" {
  * Register a service to the Celix framework.
  *
  * The service will be registered async on the Celix event loop thread. This means that service registration is (probably)
- * not yet concluded when this function returns. Use celix_bundleContext_waitForAsyncRegistration to synchronise with the
+ * not yet concluded when this function returns, but is added to the event loop.
+ * Use celix_bundleContext_waitForAsyncRegistration to synchronise with the
  * actual service registration in the framework's service registry.
  *
  * @param ctx The bundle context
@@ -79,7 +80,8 @@ long celix_bundleContext_registerService(celix_bundle_context_t *ctx, void *svc,
  * the ungetService function of the service factory will be called.
  *
  * The service will be registered async on the Celix event loop thread. This means that service registration is (probably)
- * not yet concluded when this function returns. Use celix_bundleContext_waitForAsyncRegistration to synchronise with the
+ * not yet concluded when this function returns, but is added to the event loop.
+ * Use celix_bundleContext_waitForAsyncRegistration to synchronise with the
  * actual service registration in the framework's service registry.
  *
  * @param ctx The bundle context
@@ -197,7 +199,8 @@ typedef struct celix_service_registration_options {
  * Register a service to the Celix framework using the provided service registration options.
  *
  * The service will be registered async on the Celix event loop thread. This means that service registration is (probably)
- * not yet concluded when this function returns. Use celix_bundleContext_waitForAsyncRegistration to synchronise with the
+ * not yet concluded when this function returns, but is added to the event loop..
+ * Use celix_bundleContext_waitForAsyncRegistration to synchronise with the
  * actual service registration in the framework's service registry.
  *
  * @param ctx The bundle context
@@ -218,10 +221,20 @@ long celix_bundleContext_registerServiceWithOptions(celix_bundle_context_t *ctx,
 
 /**
  * Waits til the async service registration for the provided serviceId is done.
- * Silently ignore service < 0.
+ * Silently ignore service ids < 0.
+ * Will directly return if there is no pending service registration for the provided service id.
  */
 void celix_bundleContext_waitForAsyncRegistration(celix_bundle_context_t* ctx, long serviceId);
 
+/**
+ * Checks whether a service for the provided service id is registered in the service registry.
+ * Note return false if the service for the provided service id is still pending in the event loop.
+ * Silently ignore service ids < 0 (returns false).
+ *
+ * Returns true if the service is registered in the service registry.
+ */
+bool celix_bundleContext_isServiceRegistered(celix_bundle_context_t* ctx, long serviceId);
+
 
 /**
  * Unregister the service or service factory with service id.
diff --git a/libs/framework/include/service_registry.h b/libs/framework/include/service_registry.h
index 44442e8..b9f1ad3 100644
--- a/libs/framework/include/service_registry.h
+++ b/libs/framework/include/service_registry.h
@@ -93,6 +93,8 @@ celix_status_t celix_serviceRegistry_addServiceListener(celix_service_registry_t
 
 celix_status_t celix_serviceRegistry_removeServiceListener(celix_service_registry_t *reg, celix_service_listener_t *listener);
 
+bool celix_serviceRegistry_isServiceRegistered(celix_service_registry_t* reg, long serviceId);
+
 celix_status_t
 celix_serviceRegistry_registerService(
         celix_service_registry_t *reg,
diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c
index 70aa37c..29bd2ea 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -557,6 +557,10 @@ void celix_bundleContext_waitForAsyncRegistration(celix_bundle_context_t* ctx, l
     }
 }
 
+bool celix_bundleContext_isServiceRegistered(celix_bundle_context_t* ctx, long serviceId) {
+    return celix_serviceRegistry_isServiceRegistered(ctx->framework->registry, serviceId);
+}
+
 static void celix_bundleContext_unregisterServiceInternal(celix_bundle_context_t *ctx, long serviceId, bool async, void *data, void (*done)(void*)) {
     long found = -1L;
     if (ctx != NULL && serviceId >= 0) {
@@ -1136,8 +1140,12 @@ bool celix_bundleContext_useServiceWithOptions(
         struct timespec start;
         clock_gettime(CLOCK_MONOTONIC, &start);
 
-        long id = celix_framework_fireGenericEvent(ctx->framework, -1, celix_bundle_getId(ctx->bundle), "use service", &data, celix_bundleContext_useServiceWithOptionsCallback, NULL, NULL);
-        celix_framework_waitForGenericEvent(ctx->framework, id);
+        if (celix_framework_isCurrentThreadTheEventLoop(ctx->framework)) {
+            celix_bundleContext_useServiceWithOptionsCallback(&data);
+        } else {
+            long id = celix_framework_fireGenericEvent(ctx->framework, -1, celix_bundle_getId(ctx->bundle), "use service", &data, celix_bundleContext_useServiceWithOptionsCallback, NULL, NULL);
+            celix_framework_waitForGenericEvent(ctx->framework, id);
+        }
 
         while (!data.called && opts->waitTimeoutInSeconds > 0) {
             struct timespec now;
@@ -1147,8 +1155,12 @@ bool celix_bundleContext_useServiceWithOptions(
                 break;
             }
             usleep(10);
-            id = celix_framework_fireGenericEvent(ctx->framework, -1, celix_bundle_getId(ctx->bundle), "use service", &data, celix_bundleContext_useServiceWithOptionsCallback, NULL, NULL);
-            celix_framework_waitForGenericEvent(ctx->framework, id);
+            if (celix_framework_isCurrentThreadTheEventLoop(ctx->framework)) {
+                celix_bundleContext_useServiceWithOptionsCallback(&data);
+            } else {
+                long id = celix_framework_fireGenericEvent(ctx->framework, -1, celix_bundle_getId(ctx->bundle), "use service", &data, celix_bundleContext_useServiceWithOptionsCallback, NULL, NULL);
+                celix_framework_waitForGenericEvent(ctx->framework, id);
+            }
         }
         return data.called;
     }
@@ -1181,8 +1193,12 @@ size_t celix_bundleContext_useServicesWithOptions(
         data.opts = *opts;
         data.called = false;
 
-        long id = celix_framework_fireGenericEvent(ctx->framework, -1, celix_bundle_getId(ctx->bundle), "use services", &data, celix_bundleContext_useServicesWithOptionsCallback, NULL, NULL);
-        celix_framework_waitForGenericEvent(ctx->framework, id);
+        if (celix_framework_isCurrentThreadTheEventLoop(ctx->framework)) {
+            celix_bundleContext_useServiceWithOptionsCallback(&data);
+        } else {
+            long id = celix_framework_fireGenericEvent(ctx->framework, -1, celix_bundle_getId(ctx->bundle),"use services", &data, celix_bundleContext_useServicesWithOptionsCallback, NULL, NULL);
+            celix_framework_waitForGenericEvent(ctx->framework, id);
+        }
         count = data.count;
     }
     return count;
diff --git a/libs/framework/src/service_registry.c b/libs/framework/src/service_registry.c
index c8570d3..1034210 100644
--- a/libs/framework/src/service_registry.c
+++ b/libs/framework/src/service_registry.c
@@ -1167,6 +1167,26 @@ long celix_serviceRegistry_nextSvcId(celix_service_registry_t* registry) {
     return scvId;
 }
 
+bool celix_serviceRegistry_isServiceRegistered(celix_service_registry_t* reg, long serviceId) {
+    bool isRegistered = false;
+    if (serviceId >= 0) {
+        celixThreadRwlock_readLock(&reg->lock);
+        hash_map_iterator_t iter = hashMapIterator_construct(reg->serviceRegistrations);
+        while (!isRegistered && hashMapIterator_hasNext(&iter)) {
+            celix_array_list_t *regs = hashMapIterator_nextValue(&iter);
+            for (int i = 0; i < celix_arrayList_size(regs); ++i) {
+                service_registration_t* r = celix_arrayList_get(regs, i);
+                if (serviceId == serviceRegistration_getServiceId(r)) {
+                    isRegistered = true;
+                    break;
+                }
+            }
+        }
+        celixThreadRwlock_unlock(&reg->lock);
+    }
+    return isRegistered;
+}
+
 void celix_serviceRegistry_unregisterService(celix_service_registry_t* registry, celix_bundle_t* bnd, long serviceId) {
     service_registration_t *reg = NULL;
     celixThreadRwlock_readLock(&registry->lock);