Implement refcounting for notifications

This commit is contained in:
Benedikt Heine 2018-07-06 19:41:02 +02:00
parent c5c4b2cafb
commit 837b4fe125
5 changed files with 54 additions and 12 deletions

View File

@ -282,7 +282,7 @@ static void on_notify(GDBusConnection *connection,
// The message got discarded
if (id == 0) {
signal_notification_closed(n, 2);
notification_free(n);
notification_unref(n);
}
wake_up();

View File

@ -42,6 +42,10 @@ const char *enum_to_string_fullscreen(enum behavior_fullscreen in)
}
}
struct _notification_private {
gint refcount;
};
/* see notification.h */
void notification_print(const struct notification *n)
{
@ -206,12 +210,28 @@ void rawimage_free(struct raw_image *i)
g_free(i);
}
static void notification_private_free(NotificationPrivate *p)
{
g_free(p);
}
/* see notification.h */
void notification_free(struct notification *n)
void notification_ref(struct notification *n)
{
assert(n->priv->refcount > 0);
g_atomic_int_inc(&n->priv->refcount);
}
/* see notification.h */
void notification_unref(struct notification *n)
{
if (!n)
return;
assert(n->priv->refcount > 0);
if (!g_atomic_int_dec_and_test(&n->priv->refcount))
return;
g_free(n->appname);
g_free(n->summary);
g_free(n->body);
@ -228,6 +248,8 @@ void notification_free(struct notification *n)
actions_free(n->actions);
rawimage_free(n->raw_icon);
notification_private_free(n->priv);
g_free(n);
}
@ -255,11 +277,21 @@ void notification_replace_single_field(char **haystack,
g_free(input);
}
static NotificationPrivate *notification_private_create(void)
{
NotificationPrivate *priv = g_malloc0(sizeof(NotificationPrivate));
g_atomic_int_set(&priv->refcount, 1);
return priv;
}
/* see notification.h */
struct notification *notification_create(void)
{
struct notification *n = g_malloc0(sizeof(struct notification));
n->priv = notification_private_create();
/* Unparameterized default values */
n->first_render = true;
n->markup = settings.markup;

View File

@ -42,7 +42,10 @@ struct actions {
gsize count;
};
typedef struct _notification_private NotificationPrivate;
struct notification {
NotificationPrivate *priv;
int id;
char *dbus_client;
@ -90,11 +93,18 @@ struct notification {
* - the default (if it's not needed to be freed later)
* - its undefined representation (NULL, -1)
*
* The reference counter is set to 1.
*
* This function is guaranteed to return a valid pointer.
* @returns The generated notification
*/
struct notification *notification_create(void);
/**
* Increase the reference counter of the notification.
*/
void notification_ref(struct notification *n);
/**
* Sanitize values of notification, apply all matching rules
* and generate derived fields.
@ -118,11 +128,11 @@ void actions_free(struct actions *a);
void rawimage_free(struct raw_image *i);
/**
* Free the memory used by the given notification.
* Decrease the reference counter of the notification.
*
* @param n (nullable): pointer to #notification
* If the reference count drops to 0, the object gets freed.
*/
void notification_free(struct notification *n);
void notification_unref(struct notification *n);
/**
* Helper function to compare two given notifications.

View File

@ -191,7 +191,7 @@ static bool queues_stack_duplicate(struct notification *n)
if ( allqueues[i] == displayed )
n->start = time_monotonic_now();
notification_free(orig);
notification_unref(orig);
return true;
}
}
@ -218,7 +218,7 @@ bool queues_notification_replace_id(struct notification *new)
notification_run_script(new);
}
notification_free(old);
notification_unref(old);
return true;
}
}
@ -278,12 +278,12 @@ void queues_history_push(struct notification *n)
if (!n->history_ignore) {
if (settings.history_length > 0 && history->length >= settings.history_length) {
struct notification *to_free = g_queue_pop_head(history);
notification_free(to_free);
notification_unref(to_free);
}
g_queue_push_tail(history, n);
} else {
notification_free(n);
notification_unref(n);
}
}
@ -488,7 +488,7 @@ bool queues_pause_status(void)
static void teardown_notification(gpointer data)
{
struct notification *n = data;
notification_free(n);
notification_unref(n);
}
/* see queues.h */

View File

@ -121,8 +121,8 @@ SUITE(suite_notification)
struct notification *n[2] = {a, b};
RUN_TEST1(test_notification_is_duplicate, (void*) n);
notification_free(a);
notification_free(b);
notification_unref(a);
notification_unref(b);
RUN_TEST(test_notification_replace_single_field);