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 2018/07/11 08:30:35 UTC

celix git commit: 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.

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 <pe...@gmail.com>
Authored: Wed Jul 11 10:29:24 2018 +0200
Committer: Pepijn Noltes <pe...@gmail.com>
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_