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
 | ||||
|         if (id == 0) { | ||||
|                 signal_notification_closed(n, 2); | ||||
|                 notification_free(n); | ||||
|                 notification_unref(n); | ||||
|         } | ||||
| 
 | ||||
|         wake_up(); | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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. | ||||
|  | ||||
							
								
								
									
										10
									
								
								src/queues.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/queues.c
									
									
									
									
									
								
							| @ -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 */ | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Benedikt Heine
						Benedikt Heine