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
	 Benedikt Heine
						Benedikt Heine