This is an automated email from the ASF dual-hosted git repository.
pengzheng pushed a commit to branch feature/refactor_bundle_cache
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to refs/heads/feature/refactor_bundle_cache
by this push:
new 38176b64 Fire and forget bundle lifecycle handler.
new cb2501b6 Merge remote-tracking branch
'apache/feature/refactor_bundle_cache' into feature/refactor_bundle_cache
38176b64 is described below
commit 38176b645e46f87adf20e7e15ed0ebb48b373c4a
Author: PengZheng <[email protected]>
AuthorDate: Thu Feb 23 11:59:48 2023 +0800
Fire and forget bundle lifecycle handler.
---
libs/framework/src/framework.c | 6 ++--
.../src/framework_bundle_lifecycle_handler.c | 41 ++++++++++------------
libs/framework/src/framework_private.h | 11 +++---
3 files changed, 26 insertions(+), 32 deletions(-)
diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c
index ec2d4aa3..bdde2737 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -295,6 +295,7 @@ celix_status_t framework_create(framework_pt *out,
celix_properties_t* config) {
}
//setup framework bundle lifecycle handling
+ celixThreadCondition_init(&framework->bundleLifecycleHandling.cond, NULL);
celixThreadMutex_create(&framework->bundleLifecycleHandling.mutex, NULL);
framework->bundleLifecycleHandling.bundleLifecycleHandlers =
celix_arrayList_create();
@@ -369,9 +370,10 @@ celix_status_t framework_destroy(framework_pt framework) {
celixThreadMutex_destroy(&framework->installedBundles.mutex);
//teardown framework bundle lifecycle handling
- celixThreadMutex_destroy(&framework->bundleLifecycleHandling.mutex);
assert(celix_arrayList_size(framework->bundleLifecycleHandling.bundleLifecycleHandlers)
== 0);
celix_arrayList_destroy(framework->bundleLifecycleHandling.bundleLifecycleHandlers);
+ celixThreadMutex_destroy(&framework->bundleLifecycleHandling.mutex);
+ celixThreadCondition_destroy(&framework->bundleLifecycleHandling.cond);
hashMap_destroy(framework->installRequestMap, false, false);
@@ -1194,7 +1196,7 @@ static void* framework_shutdown(void *framework) {
fw_log(fw->logger, CELIX_LOG_LEVEL_TRACE, "Celix framework shutting down");
- celix_framework_cleanupBundleLifecycleHandlers(fw, true);
+ celix_framework_waitForBundleLifecycleHandlers(fw);
celix_array_list_t *stopEntries = celix_arrayList_create();
celix_framework_bundle_entry_t *fwEntry = NULL;
diff --git a/libs/framework/src/framework_bundle_lifecycle_handler.c
b/libs/framework/src/framework_bundle_lifecycle_handler.c
index 882281ad..c0851943 100644
--- a/libs/framework/src/framework_bundle_lifecycle_handler.c
+++ b/libs/framework/src/framework_bundle_lifecycle_handler.c
@@ -23,6 +23,15 @@
#include "celix_log.h"
#include "bundle.h"
+static void celix_framework_cleanupBundleLifecycleHandler(celix_framework_t*
fw, celix_framework_bundle_lifecycle_handler_t *handler) {
+ celixThreadMutex_lock(&fw->bundleLifecycleHandling.mutex);
+
celix_arrayList_remove(fw->bundleLifecycleHandling.bundleLifecycleHandlers,
handler);
+ free(handler->updatedBundleUrl);
+ free(handler);
+ celixThreadCondition_broadcast(&fw->bundleLifecycleHandling.cond);
+ celixThreadMutex_unlock(&fw->bundleLifecycleHandling.mutex);
+}
+
/**
* Functions focusing on handling stop, start, uninstall or update bundle
commands so that they will not be executed on the celix Event thread.
*/
@@ -44,11 +53,10 @@ static void*
celix_framework_BundleLifecycleHandlingThread(void *data) {
celix_framework_updateBundleEntry(handler->framework,
handler->bndEntry, handler->updatedBundleUrl);
break;
}
- int doneVal = 1;
- __atomic_store(&handler->done, &doneVal, __ATOMIC_SEQ_CST);
if (handler->command != CELIX_BUNDLE_LIFECYCLE_UNINSTALL) {
celix_framework_bundleEntry_decreaseUseCount(handler->bndEntry);
}
+ celix_framework_cleanupBundleLifecycleHandler(handler->framework, handler);
return NULL;
}
@@ -65,27 +73,12 @@ static const char*
celix_bundleLifecycleCommand_getDesc(enum celix_bundle_lifecy
}
}
-void celix_framework_cleanupBundleLifecycleHandlers(celix_framework_t* fw,
bool waitTillEmpty) {
+void celix_framework_waitForBundleLifecycleHandlers(celix_framework_t* fw) {
celixThreadMutex_lock(&fw->bundleLifecycleHandling.mutex);
- bool cont = true;
- while (cont) {
- cont = false; //only continue if thread is joined or if waitTillEmpty
and list is not empty.
- for (int i = 0; i <
celix_arrayList_size(fw->bundleLifecycleHandling.bundleLifecycleHandlers); ++i)
{
- celix_framework_bundle_lifecycle_handler_t* handler =
celix_arrayList_get(fw->bundleLifecycleHandling.bundleLifecycleHandlers, i);
- if (__atomic_load_n(&handler->done, __ATOMIC_RELAXED) > 0) {
- celixThread_join(handler->thread, NULL);
- fw_log(fw->logger, CELIX_LOG_LEVEL_TRACE, "Joined thread for
%s bundle %li",
- celix_bundleLifecycleCommand_getDesc(handler->command)
, handler->bndId);
-
celix_arrayList_removeAt(fw->bundleLifecycleHandling.bundleLifecycleHandlers,
i);
- free(handler->updatedBundleUrl);
- free(handler);
- cont = true;
- break;
- }
- }
- if (!cont) {
- cont = waitTillEmpty &&
celix_arrayList_size(fw->bundleLifecycleHandling.bundleLifecycleHandlers) != 0;
- }
+ while
(celix_arrayList_size(fw->bundleLifecycleHandling.bundleLifecycleHandlers) !=
0) {
+ fw_log(fw->logger, CELIX_LOG_LEVEL_TRACE, "%d bundle lifecycle
handlers left, waiting",
+
celix_arrayList_size(fw->bundleLifecycleHandling.bundleLifecycleHandlers));
+
celixThreadCondition_timedwaitRelative(&fw->bundleLifecycleHandling.cond,
&fw->bundleLifecycleHandling.mutex, 5, 0);
}
celixThreadMutex_unlock(&fw->bundleLifecycleHandling.mutex);
}
@@ -103,7 +96,9 @@ static void
celix_framework_createAndStartBundleLifecycleHandler(celix_framework
fw_log(fw->logger, CELIX_LOG_LEVEL_TRACE, "Creating thread for %s bundle
%li",
celix_bundleLifecycleCommand_getDesc(handler->command) ,
handler->bndId);
- celixThread_create(&handler->thread, NULL,
celix_framework_BundleLifecycleHandlingThread, handler);
+ celix_thread_t handlerTask;
+ celixThread_create(&handlerTask, NULL,
celix_framework_BundleLifecycleHandlingThread, handler);
+ celixThread_detach(handlerTask);
celixThreadMutex_unlock(&fw->bundleLifecycleHandling.mutex);
}
diff --git a/libs/framework/src/framework_private.h
b/libs/framework/src/framework_private.h
index b6fd06ce..3f7d21a5 100644
--- a/libs/framework/src/framework_private.h
+++ b/libs/framework/src/framework_private.h
@@ -115,13 +115,11 @@ enum celix_bundle_lifecycle_command {
};
typedef struct celix_framework_bundle_lifecycle_handler {
- celix_thread_t thread;
celix_framework_t* framework;
celix_framework_bundle_entry_t* bndEntry;
long bndId;
char* updatedBundleUrl; //only relevant and present for update command
enum celix_bundle_lifecycle_command command;
- int done; //NOTE atomic -> 0 not done, 1 done (thread can be joined)
} celix_framework_bundle_lifecycle_handler_t;
struct celix_framework {
@@ -182,6 +180,7 @@ struct celix_framework {
long nextGenericEventId;
struct {
+ celix_thread_cond_t cond;
celix_thread_mutex_t mutex; //protects below
celix_array_list_t* bundleLifecycleHandlers; //entry =
celix_framework_bundle_lifecycle_handler_t*
} bundleLifecycleHandling;
@@ -402,7 +401,6 @@ celix_status_t
celix_framework_uninstallBundleOnANonCelixEventThread(celix_frame
/**
* Update (and if needed stop and start) a bundle and ensure that this is not
done on the Celix event thread.
* Will spawn a thread if needed.
- * @param fw The Celix framework
* @param bndEntry A bnd entry
* @param forceSpawnThread If the true, the start bundle will always be done
on a spawn thread
* @return CELIX_SUCCESS of the call went alright.
@@ -410,11 +408,10 @@ celix_status_t
celix_framework_uninstallBundleOnANonCelixEventThread(celix_frame
celix_status_t
celix_framework_updateBundleOnANonCelixEventThread(celix_framework_t* fw,
celix_framework_bundle_entry_t* bndEntry, const char* updatedBundleUrl, bool
forceSpawnThread);
/**
- * cleanup finished bundle lifecyles threads.
- * @param fw The framework.
- * @param waitTillEmpty Whether to wait for all threads to be finished.
+ * Wait for all bundle lifecycle handlers finishing their jobs.
+ * @param fw The Celix framework
*/
-void celix_framework_cleanupBundleLifecycleHandlers(celix_framework_t* fw,
bool waitTillEmpty);
+void celix_framework_waitForBundleLifecycleHandlers(celix_framework_t* fw);
/**
* Start a bundle. Cannot be called on the Celix event thread.