Repository: celix Updated Branches: refs/heads/develop 3415b8f3e -> d85590363
CELIX-452: And sync call for the release/retain concept for service_tracker/service listener. This ensure that the removing calls for services/service_listeners only return when there are no users anymore. Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/d8559036 Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/d8559036 Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/d8559036 Branch: refs/heads/develop Commit: d855903631f2bbf0aa4e042cee380574a769f2c9 Parents: 3415b8f Author: Pepijn Noltes <[email protected]> Authored: Wed Jul 11 10:29:24 2018 +0200 Committer: Pepijn Noltes <[email protected]> Committed: Wed Jul 11 10:29:24 2018 +0200 ---------------------------------------------------------------------- .../civetweb/src/bundle_activator.c | 3 ++ libs/framework/src/framework.c | 49 +++++++++++++------- libs/framework/src/service_tracker.c | 24 ++++++++-- libs/framework/src/service_tracker_private.h | 1 + libs/utils/include/celix_utils_api.h | 5 ++ 5 files changed, 60 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/d8559036/examples/celix-examples/civetweb/src/bundle_activator.c ---------------------------------------------------------------------- diff --git a/examples/celix-examples/civetweb/src/bundle_activator.c b/examples/celix-examples/civetweb/src/bundle_activator.c index cae9616..17892fb 100644 --- a/examples/celix-examples/civetweb/src/bundle_activator.c +++ b/examples/celix-examples/civetweb/src/bundle_activator.c @@ -21,9 +21,12 @@ #include "celix_bundle_activator.h" #include "celix_bundle.h" #include "shell.h" +#include "celix_utils_api.h" //for open_memstream for APPLE,BSD,ANDROID #include <civetweb.h> #include <string.h> +#include <stdio.h> + typedef struct activator_data { celix_bundle_context_t *ctx; http://git-wip-us.apache.org/repos/asf/celix/blob/d8559036/libs/framework/src/framework.c ---------------------------------------------------------------------- diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c index 8f72521..39622e4 100644 --- a/libs/framework/src/framework.c +++ b/libs/framework/src/framework.c @@ -31,6 +31,7 @@ #include <dlfcn.h> #endif #include <uuid/uuid.h> +#include <assert.h> #include "framework_private.h" #include "constants.h" @@ -153,6 +154,7 @@ typedef struct celix_fw_service_listener_entry { celix_thread_mutex_t mutex; //protects retainedReferences and useCount celix_array_list_t* retainedReferences; + celix_thread_cond_t useCond; size_t useCount; } celix_fw_service_listener_entry_t; @@ -167,6 +169,7 @@ static inline celix_fw_service_listener_entry_t* listener_create(celix_bundle_t entry->useCount = 1; celixThreadMutex_create(&entry->mutex, NULL); + celixThreadCondition_init(&entry->useCond, NULL); return entry; } @@ -176,27 +179,38 @@ static inline void listener_retain(celix_fw_service_listener_entry_t *entry) { celixThreadMutex_unlock(&entry->mutex); } -static inline void listener_release(celix_framework_t* framework, celix_fw_service_listener_entry_t *entry) { +static inline void listener_release(celix_fw_service_listener_entry_t *entry) { celixThreadMutex_lock(&entry->mutex); + assert(entry->useCount > 0); entry->useCount -= 1; - int count = entry->useCount; + if (entry->useCount == 0) { + celixThreadCondition_signal(&entry->useCond); + } celixThreadMutex_unlock(&entry->mutex); - //use count == 0 -> safe to destroy. +} - if (count == 0) { - //destroy - int rSize = arrayList_size(entry->retainedReferences); - for (int i = 0; i < rSize; i += 1) { - service_reference_pt ref = arrayList_get(entry->retainedReferences, i); - if (ref != NULL) { - serviceRegistry_ungetServiceReference(framework->registry, entry->bundle, ref); // decrease retain counter - } +static inline void listener_waitAndDestroy(celix_framework_t *framework, celix_fw_service_listener_entry_t *entry) { + celixThreadMutex_lock(&entry->mutex); + while(entry->useCount != 0) { + celixThreadCondition_wait(&entry->useCond, &entry->mutex); + } + celixThreadMutex_unlock(&entry->mutex); + + + //use count == 0 -> safe to destroy. + //destroy + int rSize = arrayList_size(entry->retainedReferences); + for (int i = 0; i < rSize; i += 1) { + service_reference_pt ref = arrayList_get(entry->retainedReferences, i); + if (ref != NULL) { + serviceRegistry_ungetServiceReference(framework->registry, entry->bundle, ref); // decrease retain counter } - celix_filter_destroy(entry->filter); - celix_arrayList_destroy(entry->retainedReferences); - celixThreadMutex_destroy(&entry->mutex); - free(entry); } + celix_filter_destroy(entry->filter); + celix_arrayList_destroy(entry->retainedReferences); + celixThreadMutex_destroy(&entry->mutex); + celixThreadCondition_destroy(&entry->useCond); + free(entry); } framework_logger_pt logger; @@ -1632,7 +1646,8 @@ void fw_removeServiceListener(framework_pt framework, bundle_pt bundle, celix_se } if (match != NULL) { - listener_release(framework, match); + listener_release(match); + listener_waitAndDestroy(framework, match); } } @@ -1821,7 +1836,7 @@ void fw_serviceChanged(framework_pt framework, celix_service_event_type_t eventT } } - listener_release(framework, entry); //decrease usage, so that the listener can be destroyed (if use count is now 0) + listener_release(entry); //decrease usage, so that the listener can be destroyed (if use count is now 0) } celix_arrayList_destroy(copy); } http://git-wip-us.apache.org/repos/asf/celix/blob/d8559036/libs/framework/src/service_tracker.c ---------------------------------------------------------------------- diff --git a/libs/framework/src/service_tracker.c b/libs/framework/src/service_tracker.c index 4d7798c..4e13275 100644 --- a/libs/framework/src/service_tracker.c +++ b/libs/framework/src/service_tracker.c @@ -52,6 +52,7 @@ static inline celix_tracked_entry_t* tracked_create(service_reference_pt ref, vo tracked->useCount = 1; celixThreadMutex_create(&tracked->mutex, NULL); + celixThreadCondition_init(&tracked->useCond, NULL); return tracked; } @@ -63,15 +64,25 @@ static inline void tracked_retain(celix_tracked_entry_t *tracked) { static inline void tracked_release(celix_tracked_entry_t *tracked) { celixThreadMutex_lock(&tracked->mutex); + assert(tracked->useCount > 0); tracked->useCount -= 1; - size_t count = tracked->useCount; + if (tracked->useCount == 0) { + celixThreadCondition_signal(&tracked->useCond); + } celixThreadMutex_unlock(&tracked->mutex); +} - if (count == 0) { - //destroy - celixThreadMutex_destroy(&tracked->mutex); - free(tracked); +static inline void tracked_waitAndDestroy(celix_tracked_entry_t *tracked) { + celixThreadMutex_lock(&tracked->mutex); + while (tracked->useCount != 0) { + celixThreadCondition_wait(&tracked->useCond, &tracked->mutex); } + celixThreadMutex_unlock(&tracked->mutex); + + //destroy + celixThreadMutex_destroy(&tracked->mutex); + celixThreadCondition_destroy(&tracked->useCond); + free(tracked); } celix_status_t serviceTracker_create(bundle_context_pt context, const char * service, service_tracker_customizer_pt customizer, service_tracker_pt *tracker) { @@ -522,6 +533,9 @@ static void serviceTracker_untrackTracked(celix_service_tracker_t *tracker, celi serviceTracker_invokeRemovingService(tracker, tracked); bundleContext_ungetServiceReference(tracker->context, tracked->reference); tracked_release(tracked); + + //Wait till the useCount is 0, because the untrack should only return if the service is not used anymore. + tracked_waitAndDestroy(tracked); } } http://git-wip-us.apache.org/repos/asf/celix/blob/d8559036/libs/framework/src/service_tracker_private.h ---------------------------------------------------------------------- diff --git a/libs/framework/src/service_tracker_private.h b/libs/framework/src/service_tracker_private.h index eccda39..d772dc1 100644 --- a/libs/framework/src/service_tracker_private.h +++ b/libs/framework/src/service_tracker_private.h @@ -69,6 +69,7 @@ struct celix_tracked_entry { bundle_t *serviceOwner; celix_thread_mutex_t mutex; //protects useCount + celix_thread_cond_t useCond; size_t useCount; }; http://git-wip-us.apache.org/repos/asf/celix/blob/d8559036/libs/utils/include/celix_utils_api.h ---------------------------------------------------------------------- diff --git a/libs/utils/include/celix_utils_api.h b/libs/utils/include/celix_utils_api.h index d7289eb..48324c3 100644 --- a/libs/utils/include/celix_utils_api.h +++ b/libs/utils/include/celix_utils_api.h @@ -31,4 +31,9 @@ #include "version_range.h" #include "thpool.h" +#if defined(BSD) || defined(__APPLE__) || defined(__ANDROID__) +#include "memstream/open_memstream.h" +#include "memstream/fmemopen.h" +#endif + #endif //CELIX_CELIX_UTILS_API_H_
