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 <[email protected]> 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);
