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

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

commit 72478e80e75016b791919df3867720c70c22668a
Author: Pepijn Noltes <[email protected]>
AuthorDate: Sun Jun 25 20:23:59 2023 +0200

    Add a retain guard for scheduled event based on the __cleanup__ attribute
---
 libs/framework/src/celix_scheduled_event.c | 11 +++++++++--
 libs/framework/src/celix_scheduled_event.h | 25 ++++++++++++++++++++++++-
 libs/framework/src/framework.c             | 18 ++++++------------
 3 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/libs/framework/src/celix_scheduled_event.c 
b/libs/framework/src/celix_scheduled_event.c
index 42f85f0c..cada9488 100644
--- a/libs/framework/src/celix_scheduled_event.c
+++ b/libs/framework/src/celix_scheduled_event.c
@@ -137,14 +137,15 @@ static void 
celix_scheduledEvent_destroy(celix_scheduled_event_t* event) {
     free(event);
 }
 
-void celix_scheduledEvent_retain(celix_scheduled_event_t* event) {
+celix_scheduled_event_t* celix_scheduledEvent_retain(celix_scheduled_event_t* 
event) {
     if (event == NULL) {
-        return;
+        return NULL;
     }
 
     celixThreadMutex_lock(&event->mutex);
     event->useCount += 1;
     celixThreadMutex_unlock(&event->mutex);
+    return event;
 }
 
 void celix_scheduledEvent_release(celix_scheduled_event_t* event) {
@@ -162,6 +163,12 @@ void celix_scheduledEvent_release(celix_scheduled_event_t* 
event) {
     }
 }
 
+void celix_ScheduledEvent_cleanup(celix_scheduled_event_t** event) {
+    if (event) {
+        celix_scheduledEvent_release(*event);
+    }
+}
+
 const char* celix_scheduledEvent_getName(const celix_scheduled_event_t* event) 
{ return event->eventName; }
 
 long celix_scheduledEvent_getId(const celix_scheduled_event_t* event) { return 
event->scheduledEventId; }
diff --git a/libs/framework/src/celix_scheduled_event.h 
b/libs/framework/src/celix_scheduled_event.h
index a9f92335..ea1488f4 100644
--- a/libs/framework/src/celix_scheduled_event.h
+++ b/libs/framework/src/celix_scheduled_event.h
@@ -63,8 +63,11 @@ celix_scheduled_event_t* 
celix_scheduledEvent_create(celix_framework_t* fw,
 /**
  * @brief Retain the scheduled event by increasing the use count.
  * Will silently ignore a NULL event.
+ *
+ * @param[in] event The event to retain.
+ * @return The retained event or NULL if the event is NULL.
  */
-void celix_scheduledEvent_retain(celix_scheduled_event_t* event);
+celix_scheduled_event_t* celix_scheduledEvent_retain(celix_scheduled_event_t* 
event);
 
 /**
  * @brief Release the scheduled event by decreasing the use count. If the use 
count is 0,
@@ -72,6 +75,26 @@ void celix_scheduledEvent_retain(celix_scheduled_event_t* 
event);
  */
 void celix_scheduledEvent_release(celix_scheduled_event_t* event);
 
+/**
+ * @brief Call the release of provided the scheduled event pointer.
+ * Meant to be pair with a __cleanup__ attribute or 
CELIX_SCHEDULED_EVENT_RETAIN_GUARD macro.
+ */
+void celix_ScheduledEvent_cleanup(celix_scheduled_event_t** event);
+
+/*!
+ * @brief Retain the scheduled event, add a cleanup attribute to release the 
scheduled event and
+ * return a pointer to it.
+ *
+ * This macro can be used as a guard to automatically release the scheduled 
event when leaving the current scope.
+ *
+ * @param[in] __var_name__ The name of the variable to create.
+ * @param[in] __scheduled_event__ The scheduled event to retain.
+ * @return A pointer to the retained scheduled event.
+ */
+#define CELIX_SCHEDULED_EVENT_RETAIN_GUARD(__var_name__, __scheduled_event__)  
                                        \
+    __attribute__((__cleanup__(celix_ScheduledEvent_cleanup))) 
celix_scheduled_event_t* __var_name__ =                 \
+        celix_scheduledEvent_retain(__scheduled_event__)
+
 /**
  * @brief Returns the scheduled event id.
  */
diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c
index d6d51eda..01b83464 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -2621,7 +2621,7 @@ long celix_framework_scheduleEvent(celix_framework_t* fw,
         fw_log(fw->logger, CELIX_LOG_LEVEL_ERROR, "Cannot add scheduled event 
for non existing bundle id %li.", bndId);
         return -1;
     }
-    celix_scheduled_event_t* event = celix_scheduledEvent_create(fw,
+    celix_scheduled_event_t* newEvent = celix_scheduledEvent_create(fw,
                                                                  
bndEntry->bndId,
                                                                  
celix_framework_nextScheduledEventId(fw),
                                                                  eventName,
@@ -2631,18 +2631,18 @@ long celix_framework_scheduleEvent(celix_framework_t* 
fw,
                                                                  callback,
                                                                  
removeCallbackData,
                                                                  
removeCallback);
+    CELIX_SCHEDULED_EVENT_RETAIN_GUARD(event, newEvent);
     celix_framework_bundleEntry_decreaseUseCount(bndEntry);
 
     if (event == NULL) {
         return -1L; //error logged by celix_scheduledEvent_create
     }
 
-    long eventId = celix_scheduledEvent_getId(event);
     fw_log(fw->logger,
            CELIX_LOG_LEVEL_DEBUG,
            "Added scheduled event '%s' (id=%li) for bundle '%s' (id=%li).",
            celix_scheduledEvent_getName(event),
-           eventId,
+           celix_scheduledEvent_getId(event),
            celix_bundle_getSymbolicName(bndEntry->bnd),
            bndId);
 
@@ -2651,7 +2651,7 @@ long celix_framework_scheduleEvent(celix_framework_t* fw,
     celixThreadCondition_broadcast(&fw->dispatcher.cond); //notify dispatcher 
thread for newly added scheduled event
     celixThreadMutex_unlock(&fw->dispatcher.mutex);
 
-    return eventId;
+    return celix_scheduledEvent_getId(event);
 }
 
 celix_status_t celix_framework_wakeupScheduledEvent(celix_framework_t* fw, 
long scheduledEventId) {
@@ -2677,10 +2677,7 @@ celix_status_t 
celix_framework_wakeupScheduledEvent(celix_framework_t* fw, long
 celix_status_t
 celix_framework_waitForScheduledEvent(celix_framework_t* fw, long 
scheduledEventId, double waitTimeInSeconds) {
     celixThreadMutex_lock(&fw->dispatcher.mutex);
-    celix_scheduled_event_t* event = 
celix_longHashMap_get(fw->dispatcher.scheduledEvents, scheduledEventId);
-    if (event != NULL) {
-        celix_scheduledEvent_retain(event);
-    }
+    CELIX_SCHEDULED_EVENT_RETAIN_GUARD(event, 
celix_longHashMap_get(fw->dispatcher.scheduledEvents, scheduledEventId));
     celixThreadMutex_unlock(&fw->dispatcher.mutex);
 
     if (event == NULL) {
@@ -2692,7 +2689,6 @@ celix_framework_waitForScheduledEvent(celix_framework_t* 
fw, long scheduledEvent
     }
 
     celix_status_t status = celix_scheduledEvent_wait(event, 
waitTimeInSeconds);
-    celix_scheduledEvent_release(event);
     return status;
 }
 
@@ -2705,9 +2701,8 @@ bool 
celix_framework_removeScheduledEvent(celix_framework_t* fw,
     }
 
     celixThreadMutex_lock(&fw->dispatcher.mutex);
-    celix_scheduled_event_t* event = 
celix_longHashMap_get(fw->dispatcher.scheduledEvents, scheduledEventId);
+    CELIX_SCHEDULED_EVENT_RETAIN_GUARD(event, 
celix_longHashMap_get(fw->dispatcher.scheduledEvents, scheduledEventId));
     if (event) {
-        celix_scheduledEvent_retain(event);
         celix_scheduledEvent_markForRemoval(event);
         celixThreadCondition_broadcast(&fw->dispatcher.cond); //notify 
dispatcher thread for removed scheduled event
     }
@@ -2722,7 +2717,6 @@ bool 
celix_framework_removeScheduledEvent(celix_framework_t* fw,
     if (!async) {
         celix_scheduledEvent_waitForRemoved(event);
     }
-    celix_scheduledEvent_release(event);
     return true;
 }
 

Reply via email to