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(®->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(®->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(®istry->lock);