Implement refcounting for notifications
This commit is contained in:
parent
c5c4b2cafb
commit
837b4fe125
@ -282,7 +282,7 @@ static void on_notify(GDBusConnection *connection,
|
|||||||
// The message got discarded
|
// The message got discarded
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
signal_notification_closed(n, 2);
|
signal_notification_closed(n, 2);
|
||||||
notification_free(n);
|
notification_unref(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
wake_up();
|
wake_up();
|
||||||
|
@ -42,6 +42,10 @@ const char *enum_to_string_fullscreen(enum behavior_fullscreen in)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct _notification_private {
|
||||||
|
gint refcount;
|
||||||
|
};
|
||||||
|
|
||||||
/* see notification.h */
|
/* see notification.h */
|
||||||
void notification_print(const struct notification *n)
|
void notification_print(const struct notification *n)
|
||||||
{
|
{
|
||||||
@ -206,12 +210,28 @@ void rawimage_free(struct raw_image *i)
|
|||||||
g_free(i);
|
g_free(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void notification_private_free(NotificationPrivate *p)
|
||||||
|
{
|
||||||
|
g_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
/* see notification.h */
|
/* 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)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
assert(n->priv->refcount > 0);
|
||||||
|
if (!g_atomic_int_dec_and_test(&n->priv->refcount))
|
||||||
|
return;
|
||||||
|
|
||||||
g_free(n->appname);
|
g_free(n->appname);
|
||||||
g_free(n->summary);
|
g_free(n->summary);
|
||||||
g_free(n->body);
|
g_free(n->body);
|
||||||
@ -228,6 +248,8 @@ void notification_free(struct notification *n)
|
|||||||
actions_free(n->actions);
|
actions_free(n->actions);
|
||||||
rawimage_free(n->raw_icon);
|
rawimage_free(n->raw_icon);
|
||||||
|
|
||||||
|
notification_private_free(n->priv);
|
||||||
|
|
||||||
g_free(n);
|
g_free(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,11 +277,21 @@ void notification_replace_single_field(char **haystack,
|
|||||||
g_free(input);
|
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 */
|
/* see notification.h */
|
||||||
struct notification *notification_create(void)
|
struct notification *notification_create(void)
|
||||||
{
|
{
|
||||||
struct notification *n = g_malloc0(sizeof(struct notification));
|
struct notification *n = g_malloc0(sizeof(struct notification));
|
||||||
|
|
||||||
|
n->priv = notification_private_create();
|
||||||
|
|
||||||
/* Unparameterized default values */
|
/* Unparameterized default values */
|
||||||
n->first_render = true;
|
n->first_render = true;
|
||||||
n->markup = settings.markup;
|
n->markup = settings.markup;
|
||||||
|
@ -42,7 +42,10 @@ struct actions {
|
|||||||
gsize count;
|
gsize count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _notification_private NotificationPrivate;
|
||||||
|
|
||||||
struct notification {
|
struct notification {
|
||||||
|
NotificationPrivate *priv;
|
||||||
int id;
|
int id;
|
||||||
char *dbus_client;
|
char *dbus_client;
|
||||||
|
|
||||||
@ -90,11 +93,18 @@ struct notification {
|
|||||||
* - the default (if it's not needed to be freed later)
|
* - the default (if it's not needed to be freed later)
|
||||||
* - its undefined representation (NULL, -1)
|
* - its undefined representation (NULL, -1)
|
||||||
*
|
*
|
||||||
|
* The reference counter is set to 1.
|
||||||
|
*
|
||||||
* This function is guaranteed to return a valid pointer.
|
* This function is guaranteed to return a valid pointer.
|
||||||
* @returns The generated notification
|
* @returns The generated notification
|
||||||
*/
|
*/
|
||||||
struct notification *notification_create(void);
|
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
|
* Sanitize values of notification, apply all matching rules
|
||||||
* and generate derived fields.
|
* and generate derived fields.
|
||||||
@ -118,11 +128,11 @@ void actions_free(struct actions *a);
|
|||||||
void rawimage_free(struct raw_image *i);
|
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.
|
* Helper function to compare two given notifications.
|
||||||
|
10
src/queues.c
10
src/queues.c
@ -191,7 +191,7 @@ static bool queues_stack_duplicate(struct notification *n)
|
|||||||
if ( allqueues[i] == displayed )
|
if ( allqueues[i] == displayed )
|
||||||
n->start = time_monotonic_now();
|
n->start = time_monotonic_now();
|
||||||
|
|
||||||
notification_free(orig);
|
notification_unref(orig);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +218,7 @@ bool queues_notification_replace_id(struct notification *new)
|
|||||||
notification_run_script(new);
|
notification_run_script(new);
|
||||||
}
|
}
|
||||||
|
|
||||||
notification_free(old);
|
notification_unref(old);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -278,12 +278,12 @@ void queues_history_push(struct notification *n)
|
|||||||
if (!n->history_ignore) {
|
if (!n->history_ignore) {
|
||||||
if (settings.history_length > 0 && history->length >= settings.history_length) {
|
if (settings.history_length > 0 && history->length >= settings.history_length) {
|
||||||
struct notification *to_free = g_queue_pop_head(history);
|
struct notification *to_free = g_queue_pop_head(history);
|
||||||
notification_free(to_free);
|
notification_unref(to_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_queue_push_tail(history, n);
|
g_queue_push_tail(history, n);
|
||||||
} else {
|
} else {
|
||||||
notification_free(n);
|
notification_unref(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +488,7 @@ bool queues_pause_status(void)
|
|||||||
static void teardown_notification(gpointer data)
|
static void teardown_notification(gpointer data)
|
||||||
{
|
{
|
||||||
struct notification *n = data;
|
struct notification *n = data;
|
||||||
notification_free(n);
|
notification_unref(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see queues.h */
|
/* see queues.h */
|
||||||
|
@ -121,8 +121,8 @@ SUITE(suite_notification)
|
|||||||
struct notification *n[2] = {a, b};
|
struct notification *n[2] = {a, b};
|
||||||
|
|
||||||
RUN_TEST1(test_notification_is_duplicate, (void*) n);
|
RUN_TEST1(test_notification_is_duplicate, (void*) n);
|
||||||
notification_free(a);
|
notification_unref(a);
|
||||||
notification_free(b);
|
notification_unref(b);
|
||||||
|
|
||||||
RUN_TEST(test_notification_replace_single_field);
|
RUN_TEST(test_notification_replace_single_field);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user