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:06 UTC

[celix] branch feature/async_svc_registration updated (292d844 -> 7511a9f)

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

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


    from 292d844  Refactors creating / destroy of service, bundle and meta tracker from the bundle context so that this is done on the event loop thread. Also adds async track/untrack call variants.
     new a576a90  Added async svc regitration usage to log_admin
     add 7294dbf   Fixed type in pubsub scheduler key, breaking tests inside userspace container builds
     add ee86303  Make pstm handling thread sleep time configurable
     add 23d6bce  Merge pull request #267 from Oipo/feature/configurable_sleeptime_pstm
     add deda9bd  Don't wait infinitely for server response, might never come and prevents closing of program
     add e6fe5ad  Merge pull request #269 from Oipo/bugfix/psws_infinite_wait
     add dab8fed  Document improvements
     add 62aad4f  Add page titles to documentation
     add c6388af  Merge pull request #271 from apache/add-titles
     add 9a94bd6  Add Footer
     add 864ad47  Add Footer to ZMQ
     add 915b306  add wire_v2 protocol with footer
     add 84e0619  Fix wire_v2 unit test
     add 5467050  Fix wire_v2 unit test
     add 26ece37  fix test
     add 873c6e3  Add ZMQ add tests (also zerocpy) Remove disable receive timeout when using tcp endpoint to fix tcp endpoint test
     add 996eea7  remove build warning
     add 6a9f539  Merge branch 'master' into feature/proposal_protocol_footer
     add a09cda8  update wire v2 common with uint32_t
     add be63ccf  Refactors pubsub protocol wire, added a shared static lib and merged the byte swap functions.
     add f4efaa2  Merge branch 'master' into feature/proposal_protocol_footer
     add 460d129  Avoid alloc/free calls in pubsub tcp/zmq and wire protocol
     add 892bef8  Merge branch 'master' of https://github.com/apache/celix into feature/avoid_mem_copies
     add 3be06db  Merge pull request #260 from Oipo/feature/avoid_mem_copies
     add 5e1ff87  Add void promise
     add eb8862e  Merge pull request #270 from Oipo/feature/void_promise
     add f082ee6  When a publisher has no subscribers, publishing messages is not an error. This commit sets result to succes in that case.
     add afedd8c  Merge pull request #273 from Troepje/bugfix/publish_without_client_not_an_error
     add 6bbcdb0  Ignore interface descriptors in pubsub serialization (#275)
     add eaf00f0  Reuse etcd connection to prevent storm of new sockets
     add a861d21  Merge pull request #274 from Oipo/bugfix/scalable_etcd
     add efee9f2  Feature/cpp17 promise (#272)
     add d93e47a  http -> https for doap file
     add 6bb2413  celix-site is also managed by Celix
     add 7b75d80  Celix uses GH issues instead of Jira
     add ca200f1  #277: Updated websocket sender to use mg_websocket_write instead of client_write.
     add 1d94550  Merge pull request #278 from apache/feature/277_websocket_sends_masked_frame
     add 64d9111  Fix reusing connections for etcdlib
     add c35735e  Refactors the rsa dfi export registration to use the tracker from the bundle context (which should be thread safe)
     add d2defb7  Merge pull request #281 from apache/hotfix/use_new_tracker_in_rsa_dfi
     add fd57348  etcdlib_create does not return zero as long as the malloc for that struct works.
     add dc08b88  Merge pull request #284 from unitink72/patch-1
     add 333b874  Adds test for dynamically creating and destroying a component providing a remote service which deadlocks
     add 5bf1426  Adds a stop service export thread for rsa to prevent deadlocks
     add 921ed6e  sets use of stop export service thread to true
     add 506cb88  Adds test case for create a remote service in a remote service call and fixes the deadlock issue for that test case.
     add 20f794b  Merge pull request #282 from apache/hotfix/rsa_deadlock
     new 815524c  Merge branch 'master' into feature/async_svc_registration
     new 1877032  Update bc_useService(s) so that it can be called on the event loop thread
     new 7511a9f  Fixes some issues

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 CHANGES.md                                         |   4 +
 CMakeLists.txt                                     |   8 +-
 bundles/deployment_admin/README.md                 |   4 +
 bundles/device_access/README.md                    |   4 +
 .../device_access/example/base_driver/README.md    |   4 +
 .../example/consuming_driver/README.md             |   4 +
 .../example/refining_driver/README.md              |   4 +
 bundles/http_admin/README.md                       |   4 +
 bundles/http_admin/civetweb/src/civetweb.c         |   2 +-
 bundles/http_admin/http_admin/src/http_admin.c     |   7 +-
 bundles/logging/README.md                          |   4 +
 bundles/logging/log_admin/src/celix_log_admin.c    |  45 +-
 bundles/logging/log_writers/README.md              |   4 +
 bundles/pubsub/README.md                           |   4 +
 bundles/pubsub/examples/keys/README.md             |   4 +
 .../pubsub_admin_tcp/src/pubsub_tcp_handler.c      |  27 +-
 bundles/pubsub/pubsub_admin_udp_mc/README.md       |   4 +
 .../src/pubsub_websocket_topic_sender.c            |   4 +-
 .../pubsub_admin_zmq/src/pubsub_zmq_topic_sender.c | 118 ++--
 .../pubsub_protocol_lib/CMakeLists.txt             |   8 +-
 .../gtest/CMakeLists.txt                           |  12 +-
 .../gtest/src/PS_WP_common_tests.cc                |  57 ++
 .../pubsub_protocol_lib}/gtest/src/main.cc         |   0
 .../src/pubsub_wire_protocol_common.c              |  93 ++-
 bundles/pubsub/pubsub_spi/src/pubsub_endpoint.c    |   3 +-
 .../src/pubsub_topology_manager.c                  |   5 +-
 .../src/pubsub_topology_manager.h                  |   2 +
 bundles/pubsub/pubsub_utils/gtest/CMakeLists.txt   |   1 +
 .../gtest/msg_descriptors/int_calc.descriptor      |   0
 .../src/PubSubSerializationHandlerTestSuite.cc     |  14 +
 .../src/pubsub_serialization_provider.c            |  21 +-
 bundles/pubsub/test/CMakeLists.txt                 |   6 -
 .../test/meta_data/deadlock.scope.properties       |   2 +-
 .../test/meta_data/deadlock.scope2.properties      |   2 +-
 bundles/pubsub/test/meta_data/ping.properties      |   2 +-
 bundles/pubsub/test/meta_data/ping2.properties     |   2 +-
 bundles/pubsub/test/meta_data/pong2.properties     |   2 +-
 bundles/remote_services/README.md                  |   6 +-
 bundles/remote_services/discovery_etcd/README.md   |   4 +
 .../remote_example_api/include/remote_example.h    |   2 +
 .../org.apache.celix.RemoteExample.descriptor      |   1 +
 .../src/remote_example_activator.c                 |   3 +-
 .../src/remote_example_impl.c                      |  49 +-
 .../src/remote_example_impl.h                      |   4 +-
 .../remote_service_admin_dfi/README.md             |   4 +
 .../gtest/src/rsa_client_server_tests.cc           |  20 +
 .../gtest/src/tst_activator.c                      |  34 ++
 .../gtest/src/tst_service.h                        |   2 +
 .../src/export_registration_dfi.c                  | 115 +++-
 .../src/export_registration_dfi.h                  |   6 +-
 .../src/remote_service_admin_dfi.c                 | 148 ++++-
 .../remote_services/remote_services_api/README.md  |   4 +
 bundles/remote_services/rsa_spi/README.md          |   4 +
 bundles/remote_services/topology_manager/README.md |   4 +
 bundles/shell/remote_shell/README.md               |   4 +
 bundles/shell/shell/README.md                      |   4 +
 bundles/shell/shell_tui/README.md                  |   4 +
 bundles/shell/shell_wui/README.md                  |   4 +
 doap/doap_Celix.rdf                                |  20 +-
 documents/building/README.md                       |   4 +
 documents/cmake_commands/README.md                 |   4 +
 documents/getting_started/README.md                |   4 +
 .../getting_started/creating_a_simple_bundle.md    |   6 +-
 documents/getting_started/using_services_with_c.md |   4 +
 .../getting_started/using_services_with_cxx.md     |   4 +
 documents/intro/README.md                          |   6 +-
 documents/subprojects/README.md                    |   6 +
 examples/celix-examples/README.md                  |   4 +
 examples/celix-examples/http_example/README.md     |   7 +-
 .../celix-examples/services_example_c/README.md    |   4 +
 libs/dependency_manager/README.md                  |   4 +
 libs/dependency_manager/TODO.md                    |   6 +-
 libs/dependency_manager_cxx/README.md              |   4 +
 libs/dependency_manager_cxx/TODO.md                |   6 +-
 libs/etcdlib/README.md                             |   4 +
 libs/etcdlib/api/etcdlib.h                         |  16 +-
 libs/etcdlib/src/etcd.c                            | 110 ++--
 libs/etcdlib/test/etcdlib_test.c                   |   2 +-
 .../gtest/src/bundle_context_services_test.cpp     |   6 +-
 libs/framework/include/celix_bundle_context.h      |  29 +-
 libs/framework/include/celix_framework.h           |   6 +
 libs/framework/include/service_registry.h          |   2 +
 libs/framework/src/bundle_context.c                |  39 +-
 libs/framework/src/framework.c                     |  30 +
 libs/framework/src/service_registry.c              |  30 +-
 libs/launcher/README.md                            |   4 +
 libs/utils/README.md                               |   4 +
 misc/experimental/README.md                        |   4 +
 misc/experimental/bundles/config_admin/README.md   |   4 +
 misc/experimental/promise/CMakeLists.txt           |   6 +-
 misc/experimental/promise/README.md                |   4 +
 misc/experimental/promise/api/celix/Deferred.h     | 136 ++++-
 misc/experimental/promise/api/celix/Promise.h      | 191 +++++-
 .../promise/api/celix/PromiseFactory.h             |  16 +-
 .../promise/api/celix/PromiseInvocationException.h |   6 +-
 .../promise/api/celix/impl/SharedPromiseState.h    | 654 +++++++++++++++++----
 misc/experimental/promise/gtest/CMakeLists.txt     |   1 +
 .../promise/gtest/src/PromiseTestSuite.cc          | 116 +++-
 ...PromiseTestSuite.cc => VoidPromiseTestSuite.cc} | 189 +++---
 misc/experimental/promise/src/PromiseExamples.cc   |   2 +-
 100 files changed, 2025 insertions(+), 596 deletions(-)
 copy bundles/pubsub/pubsub_protocol/{pubsub_protocol_wire_v1 => pubsub_protocol_lib}/gtest/CMakeLists.txt (67%)
 create mode 100644 bundles/pubsub/pubsub_protocol/pubsub_protocol_lib/gtest/src/PS_WP_common_tests.cc
 copy bundles/{remote_services/remote_service_admin_dfi => pubsub/pubsub_protocol/pubsub_protocol_lib}/gtest/src/main.cc (100%)
 copy libs/dfi/gtest/descriptors/example1.descriptor => bundles/pubsub/pubsub_utils/gtest/msg_descriptors/int_calc.descriptor (100%)
 copy misc/experimental/promise/gtest/src/{PromiseTestSuite.cc => VoidPromiseTestSuite.cc} (63%)


[celix] 01/04: Added async svc regitration usage to log_admin

Posted by pn...@apache.org.
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 a576a90565b0ac8701d9d61346e8bf778186c3d4
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Mon Sep 7 16:26:45 2020 +0200

    Added async svc regitration usage to log_admin
---
 bundles/logging/log_admin/src/celix_log_admin.c    | 45 ++++++++++------------
 .../gtest/src/bundle_context_services_test.cpp     |  2 +-
 libs/framework/include/celix_bundle_context.h      |  8 +++-
 libs/framework/include/celix_framework.h           |  6 +++
 libs/framework/src/bundle_context.c                | 10 +++--
 libs/framework/src/framework.c                     | 30 +++++++++++++++
 6 files changed, 72 insertions(+), 29 deletions(-)

diff --git a/bundles/logging/log_admin/src/celix_log_admin.c b/bundles/logging/log_admin/src/celix_log_admin.c
index e594abc..805233b 100644
--- a/bundles/logging/log_admin/src/celix_log_admin.c
+++ b/bundles/logging/log_admin/src/celix_log_admin.c
@@ -210,7 +210,7 @@ static void celix_logAdmin_addLogSvcForName(celix_log_admin_t* admin, const char
             opts.serviceVersion = CELIX_LOG_SERVICE_VERSION;
             opts.properties = props;
             opts.svc = &newEntry->logSvc;
-            newEntry->logSvcId = celix_bundleContext_registerServiceAsyncWithOptions(admin->ctx, &opts);
+            newEntry->logSvcId = celix_bundleContext_registerServiceWithOptionsAsync(admin->ctx, &opts);
         }
 
         if (celix_utils_stringEquals(newEntry->name, CELIX_LOG_ADMIN_FRAMEWORK_LOG_NAME)) {
@@ -232,31 +232,28 @@ static void celix_logAdmin_trackerAdd(void *handle, const celix_service_tracker_
     celix_logAdmin_addLogSvcForName(admin, name);
 }
 
-static void celix_logAdmin_remLogSvcForName(celix_log_admin_t* admin, const char* name) {
-    celix_log_service_entry_t* remEntry = NULL;
+static void celix_logAdmin_freeLogEntry(void *data) {
+    celix_log_service_entry_t* entry = data;
+    if (celix_utils_stringEquals(entry->name, CELIX_LOG_ADMIN_FRAMEWORK_LOG_NAME)) {
+        celix_framework_t* fw = celix_bundleContext_getFramework(entry->admin->ctx);
+        celix_framework_setLogCallback(fw, NULL, NULL);
+    }
+    free(entry->name);
+    free(entry);
+}
 
+static void celix_logAdmin_remLogSvcForName(celix_log_admin_t* admin, const char* name) {
     celixThreadRwlock_writeLock(&admin->lock);
     celix_log_service_entry_t* found = hashMap_get(admin->loggers, name);
     if (found != NULL) {
         found->count -= 1;
         if (found->count == 0) {
             //remove
-            remEntry = found;
             hashMap_remove(admin->loggers, name);
+            celix_bundleContext_unregisterServiceAsync(admin->ctx, found->logSvcId, found, celix_logAdmin_freeLogEntry);
         }
     }
     celixThreadRwlock_unlock(&admin->lock);
-
-    if (remEntry != NULL) {
-        if (celix_utils_stringEquals(remEntry->name, CELIX_LOG_ADMIN_FRAMEWORK_LOG_NAME)) {
-            celix_framework_t* fw = celix_bundleContext_getFramework(admin->ctx);
-            celix_framework_setLogCallback(fw, NULL, NULL);
-        }
-
-        celix_bundleContext_unregisterService(admin->ctx, remEntry->logSvcId);
-        free(remEntry->name);
-        free(remEntry);
-    }
 }
 
 
@@ -591,10 +588,10 @@ celix_log_admin_t* celix_logAdmin_create(celix_bundle_context_t *ctx) {
         opts.callbackHandle = admin;
         opts.addWithProperties = celix_logAdmin_addSink;
         opts.removeWithProperties = celix_logAdmin_remSink;
-        admin->logWriterTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
+        admin->logWriterTrackerId = celix_bundleContext_trackServicesWithOptionsAsync(ctx, &opts);
     }
 
-    admin->logServiceMetaTrackerId = celix_bundleContext_trackServiceTrackers(ctx, CELIX_LOG_SERVICE_NAME, admin, celix_logAdmin_trackerAdd, celix_logAdmin_trackerRem);
+    admin->logServiceMetaTrackerId = celix_bundleContext_trackServiceTrackersAsync(ctx, CELIX_LOG_SERVICE_NAME, admin, celix_logAdmin_trackerAdd, celix_logAdmin_trackerRem, NULL, NULL);
 
     {
         admin->controlSvc.handle = admin;
@@ -612,7 +609,7 @@ celix_log_admin_t* celix_logAdmin_create(celix_bundle_context_t *ctx) {
         opts.serviceName = CELIX_LOG_CONTROL_NAME;
         opts.serviceVersion = CELIX_LOG_CONTROL_VERSION;
         opts.svc = &admin->controlSvc;
-        admin->controlSvcId = celix_bundleContext_registerServiceWithOptions(ctx, &opts);
+        admin->controlSvcId = celix_bundleContext_registerServiceWithOptionsAsync(ctx, &opts);
     }
 
     {
@@ -629,12 +626,11 @@ celix_log_admin_t* celix_logAdmin_create(celix_bundle_context_t *ctx) {
         opts.serviceVersion = CELIX_SHELL_COMMAND_SERVICE_VERSION;
         opts.properties = props;
         opts.svc = &admin->cmdSvc;
-        admin->cmdSvcId = celix_bundleContext_registerServiceWithOptions(ctx, &opts);
+        admin->cmdSvcId = celix_bundleContext_registerServiceWithOptionsAsync(ctx, &opts);
     }
 
     //add log service for the framework
     celix_logAdmin_addLogSvcForName(admin, CELIX_LOG_ADMIN_FRAMEWORK_LOG_NAME);
-
     return admin;
 }
 
@@ -642,10 +638,11 @@ void celix_logAdmin_destroy(celix_log_admin_t *admin) {
     if (admin != NULL) {
         celix_logAdmin_remLogSvcForName(admin, CELIX_LOG_ADMIN_FRAMEWORK_LOG_NAME);
 
-        celix_bundleContext_unregisterService(admin->ctx, admin->cmdSvcId);
-        celix_bundleContext_unregisterService(admin->ctx, admin->controlSvcId);
-        celix_bundleContext_stopTracker(admin->ctx, admin->logServiceMetaTrackerId);
-        celix_bundleContext_stopTracker(admin->ctx, admin->logWriterTrackerId);
+        celix_bundleContext_unregisterServiceAsync(admin->ctx, admin->cmdSvcId, NULL, NULL);
+        celix_bundleContext_unregisterServiceAsync(admin->ctx, admin->controlSvcId, NULL, NULL);
+        celix_bundleContext_stopTrackerAsync(admin->ctx, admin->logServiceMetaTrackerId, NULL, NULL);
+        celix_bundleContext_stopTrackerAsync(admin->ctx, admin->logWriterTrackerId, NULL, NULL);
+        celix_bundleContext_waitForEvents(admin->ctx);
 
         assert(hashMap_size(admin->loggers) == 0); //note stopping service tracker tracker should triggered all needed remove events
         hashMap_destroy(admin->loggers, false, false);
diff --git a/libs/framework/gtest/src/bundle_context_services_test.cpp b/libs/framework/gtest/src/bundle_context_services_test.cpp
index 96ba33c..9e5335f 100644
--- a/libs/framework/gtest/src/bundle_context_services_test.cpp
+++ b/libs/framework/gtest/src/bundle_context_services_test.cpp
@@ -1052,7 +1052,7 @@ TEST_F(CelixBundleContextServicesTests, floodEventLoopTest) {
         localData->cond.wait_for(lck, std::chrono::seconds{30}, [&]{ return localData->ready; }); //wait til ready.
         EXPECT_TRUE(localData->ready);
     };
-    long svcId = celix_bundleContext_registerServiceAsyncWithOptions(ctx, &opts);
+    long svcId = celix_bundleContext_registerServiceWithOptionsAsync(ctx, &opts);
     EXPECT_GE(svcId, 0);
 
     int nrOfAdditionalRegistrations = 300;
diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h
index 90f733c..060a749 100644
--- a/libs/framework/include/celix_bundle_context.h
+++ b/libs/framework/include/celix_bundle_context.h
@@ -204,7 +204,7 @@ typedef struct celix_service_registration_options {
  * @param opts The pointer to the registration options. The options are only in the during registration call.
  * @return The serviceId (>= 0) or -1 if the registration was unsuccessful and -2 if the registration was cancelled (@see celix_bundleContext_reserveSvcId).
  */
-long celix_bundleContext_registerServiceAsyncWithOptions(celix_bundle_context_t *ctx, const celix_service_registration_options_t *opts);
+long celix_bundleContext_registerServiceWithOptionsAsync(celix_bundle_context_t *ctx, const celix_service_registration_options_t *opts);
 
 /**
  * Register a service to the Celix framework using the provided service registration options.
@@ -1109,6 +1109,12 @@ celix_dependency_manager_t* celix_bundleContext_getDependencyManager(celix_bundl
 
 
 /**
+ * Wait till there are event for the bundle of this bundle context.
+ */
+void celix_bundleContext_waitForEvents(celix_bundle_context_t* ctx);
+
+
+/**
  * Returns the bundle for this bundle context.
  */
 celix_bundle_t* celix_bundleContext_getBundle(const celix_bundle_context_t *ctx);
diff --git a/libs/framework/include/celix_framework.h b/libs/framework/include/celix_framework.h
index 7af1e2c..8b5482f 100644
--- a/libs/framework/include/celix_framework.h
+++ b/libs/framework/include/celix_framework.h
@@ -156,6 +156,12 @@ void celix_framework_waitForEmptyEventQueue(celix_framework_t *fw);
 void celix_framework_setLogCallback(celix_framework_t* fw, void* logHandle, void (*logFunction)(void* handle, celix_log_level_e level, const char* file, const char *function, int line, const char *format, va_list formatArgs));
 
 
+/**
+ * wait till all events for the bundle identified by the bndId are processed.
+ */
+void celix_framework_waitForEvents(celix_framework_t* fw, long bndId);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c
index 43a11cd..70aa37c 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -457,7 +457,7 @@ long celix_bundleContext_registerServiceAsync(celix_bundle_context_t *ctx, void
     opts.svc = svc;
     opts.serviceName = serviceName;
     opts.properties = properties;
-    return celix_bundleContext_registerServiceAsyncWithOptions(ctx, &opts);
+    return celix_bundleContext_registerServiceWithOptionsAsync(ctx, &opts);
 }
 
 long celix_bundleContext_registerService(bundle_context_t *ctx, void *svc, const char *serviceName, celix_properties_t *properties) {
@@ -474,7 +474,7 @@ long celix_bundleContext_registerServiceFactoryAsync(celix_bundle_context_t *ctx
     opts.factory = factory;
     opts.serviceName = serviceName;
     opts.properties = props;
-    return celix_bundleContext_registerServiceAsyncWithOptions(ctx, &opts);
+    return celix_bundleContext_registerServiceWithOptionsAsync(ctx, &opts);
 }
 
 long celix_bundleContext_registerServiceFactory(celix_bundle_context_t *ctx, celix_service_factory_t *factory, const char *serviceName, celix_properties_t *props) {
@@ -547,7 +547,7 @@ long celix_bundleContext_registerServiceWithOptions(bundle_context_t *ctx, const
     return celix_bundleContext_registerServiceWithOptionsInternal(ctx, opts, false);
 }
 
-long celix_bundleContext_registerServiceAsyncWithOptions(celix_bundle_context_t *ctx, const celix_service_registration_options_t *opts) {
+long celix_bundleContext_registerServiceWithOptionsAsync(celix_bundle_context_t *ctx, const celix_service_registration_options_t *opts) {
     return celix_bundleContext_registerServiceWithOptionsInternal(ctx, opts, true);
 }
 
@@ -1484,6 +1484,10 @@ long celix_bundleContext_trackServiceTrackersAsync(
     return celix_bundleContext_trackServiceTrackersInternal(ctx, serviceName, callbackHandle, trackerAdd, trackerRemove, true, doneCallbackData, doneCallback);
 }
 
+void celix_bundleContext_waitForEvents(celix_bundle_context_t* ctx) {
+    celix_framework_waitForEvents(ctx->framework, celix_bundle_getId(ctx->bundle));
+}
+
 celix_bundle_t* celix_bundleContext_getBundle(const celix_bundle_context_t *ctx) {
     celix_bundle_t *bnd = NULL;
     if (ctx != NULL) {
diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c
index 84eaf67..de19f63 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -2640,6 +2640,36 @@ void celix_framework_waitForEmptyEventQueue(celix_framework_t *fw) {
     celixThreadMutex_unlock(&fw->dispatcher.mutex);
 }
 
+void celix_framework_waitForEvents(celix_framework_t* fw, long bndId) {
+    assert(!celix_framework_isCurrentThreadTheEventLoop(fw));
+
+    celixThreadMutex_lock(&fw->dispatcher.mutex);
+    bool eventInProgress = true;
+    while (eventInProgress) {
+        eventInProgress = false;
+        for (int i = 0; i < fw->dispatcher.eventQueueSize; ++i) {
+            int index = (fw->dispatcher.eventQueueFirstEntry + i) % CELIX_FRAMEWORK_STATIC_EVENT_QUEUE_SIZE;
+            celix_framework_event_t* e = &fw->dispatcher.eventQueue[index];
+            if (e->bndEntry != NULL && e->bndEntry->bndId == bndId) {
+                eventInProgress = true;
+                break;
+            }
+        }
+        for (int i = 0; !eventInProgress && i < celix_arrayList_size(fw->dispatcher.dynamicEventQueue); ++i) {
+            celix_framework_event_t* e = celix_arrayList_get(fw->dispatcher.dynamicEventQueue, i);
+            if (e->bndEntry != NULL && e->bndEntry->bndId == bndId) {
+                eventInProgress = true;
+                break;
+            }
+        }
+        if (eventInProgress) {
+            celixThreadCondition_timedwaitRelative(&fw->dispatcher.cond, &fw->dispatcher.mutex, 5, 0);
+        }
+    }
+    celixThreadMutex_unlock(&fw->dispatcher.mutex);
+}
+
+
 void celix_framework_setLogCallback(celix_framework_t* fw, void* logHandle, void (*logFunction)(void* handle, celix_log_level_e level, const char* file, const char *function, int line, const char *format, va_list formatArgs)) {
     celix_frameworkLogger_setLogCallback(fw->logger, logHandle, logFunction);
 }


[celix] 04/04: Fixes some issues

Posted by pn...@apache.org.
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 7511a9fbc3ea8ffcc0779e27e99153a1c23bf3ed
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Oct 4 20:52:46 2020 +0200

    Fixes some issues
---
 bundles/http_admin/http_admin/src/http_admin.c                     | 7 ++++---
 bundles/pubsub/pubsub_spi/src/pubsub_endpoint.c                    | 3 ++-
 .../remote_example_api/org.apache.celix.RemoteExample.descriptor   | 2 +-
 libs/framework/src/bundle_context.c                                | 1 +
 4 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/bundles/http_admin/http_admin/src/http_admin.c b/bundles/http_admin/http_admin/src/http_admin.c
index ca7c93d..20b2287 100755
--- a/bundles/http_admin/http_admin/src/http_admin.c
+++ b/bundles/http_admin/http_admin/src/http_admin.c
@@ -122,17 +122,17 @@ void httpAdmin_destroy(http_admin_manager_t *admin) {
 
     //Destroy alias map by removing symbolic links first.
     unsigned int size = celix_arrayList_size(admin->aliasList);
-    for (unsigned int i = (size - 1); i < size; i--) {
+    for (int i = 0; i < size; ++i) {
         http_alias_t *alias = celix_arrayList_get(admin->aliasList, i);
 
         //Delete alias in cache directory
-        if (remove(alias->alias_path) < 0)
+        if (remove(alias->alias_path) < 0) {
             fprintf(stdout, "remove of %s failed\n", alias->alias_path);
+        }
 
         free(alias->url);
         free(alias->alias_path);
         free(alias);
-        celix_arrayList_removeAt(admin->aliasList, i);
     }
     celix_arrayList_destroy(admin->aliasList);
 
@@ -520,6 +520,7 @@ void http_admin_stopBundle(void *data, const celix_bundle_t *bundle) {
         http_alias_t *alias = arrayList_get(admin->aliasList, i);
         if(alias->bundle_id == bundle_id) {
             remove(alias->alias_path); //Delete alias in cache directory
+            free(alias->url);
             free(alias->alias_path);
             free(alias);
             celix_arrayList_removeAt(admin->aliasList, i);
diff --git a/bundles/pubsub/pubsub_spi/src/pubsub_endpoint.c b/bundles/pubsub/pubsub_spi/src/pubsub_endpoint.c
index c1a715e..e7d504f 100644
--- a/bundles/pubsub/pubsub_spi/src/pubsub_endpoint.c
+++ b/bundles/pubsub/pubsub_spi/src/pubsub_endpoint.c
@@ -170,8 +170,9 @@ celix_properties_t* pubsubEndpoint_createFromPublisherTrackerInfo(bundle_context
     data.topic = topic;
     celix_bundleContext_useBundle(ctx, bundleId, &data, retrieveTopicProperties);
 
+    pubsubEndpoint_setFields(ep, fwUUID, scope, topic, PUBSUB_PUBLISHER_ENDPOINT_TYPE, NULL, NULL, NULL, data.props);
+
     if (data.props != NULL) {
-        pubsubEndpoint_setFields(ep, fwUUID, scope, topic, PUBSUB_PUBLISHER_ENDPOINT_TYPE, NULL, NULL, NULL, data.props);
         celix_properties_destroy(data.props); //safe to delete, properties are copied in pubsubEndpoint_setFields
     }
 
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 6cbefb2..0558c7f 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
\ No newline at end of file
+createAdditionalRemoteService=createAdditionalRemoteService(#am=handle;P)N
diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c
index 29bd2ea..34a3dcb 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -1310,6 +1310,7 @@ static long celix_bundleContext_trackServicesWithOptionsInternal(celix_bundle_co
             entry->destroyEventId = celix_framework_nextEventId(ctx->framework);
             celixThreadMutex_lock(&ctx->mutex);
             entry->trackerId = ctx->nextTrackerId++;
+            trackerId = entry->trackerId;
             hashMap_put(ctx->serviceTrackers, (void *) trackerId, entry);
             celixThreadMutex_unlock(&ctx->mutex);
         }


[celix] 02/04: Merge branch 'master' into feature/async_svc_registration

Posted by pn...@apache.org.
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 815524c3f9a6409a598f7851e581d4e4c5b7b46b
Merge: a576a90 20f794b
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Oct 4 15:34:15 2020 +0200

    Merge branch 'master' into feature/async_svc_registration

 CHANGES.md                                         |   4 +
 CMakeLists.txt                                     |   8 +-
 bundles/deployment_admin/README.md                 |   4 +
 bundles/device_access/README.md                    |   4 +
 .../device_access/example/base_driver/README.md    |   4 +
 .../example/consuming_driver/README.md             |   4 +
 .../example/refining_driver/README.md              |   4 +
 bundles/http_admin/README.md                       |   4 +
 bundles/http_admin/civetweb/src/civetweb.c         |   2 +-
 bundles/logging/README.md                          |   4 +
 bundles/logging/log_writers/README.md              |   4 +
 bundles/pubsub/README.md                           |   4 +
 bundles/pubsub/examples/keys/README.md             |   4 +
 .../pubsub_admin_tcp/src/pubsub_tcp_handler.c      |  27 +-
 bundles/pubsub/pubsub_admin_udp_mc/README.md       |   4 +
 .../src/pubsub_websocket_topic_sender.c            |   4 +-
 .../pubsub_admin_zmq/src/pubsub_zmq_topic_sender.c | 118 ++--
 .../pubsub_protocol_lib/CMakeLists.txt             |   8 +-
 .../pubsub_protocol_lib}/gtest/CMakeLists.txt      |  17 +-
 .../gtest/src/PS_WP_common_tests.cc                |  57 ++
 .../pubsub_protocol_lib/gtest/src/main.cc          |  28 +-
 .../src/pubsub_wire_protocol_common.c              |  93 ++-
 .../src/pubsub_topology_manager.c                  |   5 +-
 .../src/pubsub_topology_manager.h                  |   2 +
 bundles/pubsub/pubsub_utils/gtest/CMakeLists.txt   |   1 +
 .../gtest/msg_descriptors/int_calc.descriptor      |  13 +
 .../src/PubSubSerializationHandlerTestSuite.cc     |  14 +
 .../src/pubsub_serialization_provider.c            |  21 +-
 bundles/pubsub/test/CMakeLists.txt                 |   6 -
 .../test/meta_data/deadlock.scope.properties       |   2 +-
 .../test/meta_data/deadlock.scope2.properties      |   2 +-
 bundles/pubsub/test/meta_data/ping.properties      |   2 +-
 bundles/pubsub/test/meta_data/ping2.properties     |   2 +-
 bundles/pubsub/test/meta_data/pong2.properties     |   2 +-
 bundles/remote_services/README.md                  |   6 +-
 bundles/remote_services/discovery_etcd/README.md   |   4 +
 .../remote_example_api/include/remote_example.h    |   2 +
 .../org.apache.celix.RemoteExample.descriptor      |   1 +
 .../src/remote_example_activator.c                 |   3 +-
 .../src/remote_example_impl.c                      |  49 +-
 .../src/remote_example_impl.h                      |   4 +-
 .../remote_service_admin_dfi/README.md             |   4 +
 .../gtest/src/rsa_client_server_tests.cc           |  20 +
 .../gtest/src/tst_activator.c                      |  33 ++
 .../gtest/src/tst_service.h                        |   2 +
 .../src/export_registration_dfi.c                  | 115 +++-
 .../src/export_registration_dfi.h                  |   6 +-
 .../src/remote_service_admin_dfi.c                 | 148 ++++-
 .../remote_services/remote_services_api/README.md  |   4 +
 bundles/remote_services/rsa_spi/README.md          |   4 +
 bundles/remote_services/topology_manager/README.md |   4 +
 bundles/shell/remote_shell/README.md               |   4 +
 bundles/shell/shell/README.md                      |   4 +
 bundles/shell/shell_tui/README.md                  |   4 +
 bundles/shell/shell_wui/README.md                  |   4 +
 doap/doap_Celix.rdf                                |  20 +-
 documents/building/README.md                       |   4 +
 documents/cmake_commands/README.md                 |   4 +
 documents/getting_started/README.md                |   4 +
 .../getting_started/creating_a_simple_bundle.md    |   6 +-
 documents/getting_started/using_services_with_c.md |   4 +
 .../getting_started/using_services_with_cxx.md     |   4 +
 documents/intro/README.md                          |   6 +-
 documents/subprojects/README.md                    |   6 +
 examples/celix-examples/README.md                  |   4 +
 examples/celix-examples/http_example/README.md     |   7 +-
 .../celix-examples/services_example_c/README.md    |   4 +
 libs/dependency_manager/README.md                  |   4 +
 libs/dependency_manager/TODO.md                    |   6 +-
 libs/dependency_manager_cxx/README.md              |   4 +
 libs/dependency_manager_cxx/TODO.md                |   6 +-
 libs/etcdlib/README.md                             |   4 +
 libs/etcdlib/api/etcdlib.h                         |  16 +-
 libs/etcdlib/src/etcd.c                            | 110 ++--
 libs/etcdlib/test/etcdlib_test.c                   |   2 +-
 libs/framework/src/service_registry.c              |  10 +-
 libs/launcher/README.md                            |   4 +
 libs/utils/README.md                               |   4 +
 misc/experimental/README.md                        |   4 +
 misc/experimental/bundles/config_admin/README.md   |   4 +
 misc/experimental/promise/CMakeLists.txt           |   6 +-
 misc/experimental/promise/README.md                |   4 +
 misc/experimental/promise/api/celix/Deferred.h     | 136 ++++-
 misc/experimental/promise/api/celix/Promise.h      | 191 +++++-
 .../promise/api/celix/PromiseFactory.h             |  16 +-
 .../promise/api/celix/PromiseInvocationException.h |   6 +-
 .../promise/api/celix/impl/SharedPromiseState.h    | 654 +++++++++++++++++----
 misc/experimental/promise/gtest/CMakeLists.txt     |   1 +
 .../promise/gtest/src/PromiseTestSuite.cc          | 116 +++-
 ...PromiseTestSuite.cc => VoidPromiseTestSuite.cc} | 189 +++---
 misc/experimental/promise/src/PromiseExamples.cc   |   2 +-
 91 files changed, 1903 insertions(+), 576 deletions(-)



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

Posted by pn...@apache.org.
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);