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; }
