mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 16:32:18 +01:00 
			
		
		
		
	Merge branch 'source-once-no-allocs' into 'main'
gmain: Refactor idle-once and timeout-once to avoid a closure allocation See merge request GNOME/glib!2693
This commit is contained in:
		
							
								
								
									
										225
									
								
								glib/gmain.c
									
									
									
									
									
								
							
							
						
						
									
										225
									
								
								glib/gmain.c
									
									
									
									
									
								
							| @@ -235,6 +235,7 @@ | ||||
|  | ||||
| /* Types */ | ||||
|  | ||||
| typedef struct _GIdleSource GIdleSource; | ||||
| typedef struct _GTimeoutSource GTimeoutSource; | ||||
| typedef struct _GChildWatchSource GChildWatchSource; | ||||
| typedef struct _GUnixSignalWatchSource GUnixSignalWatchSource; | ||||
| @@ -332,12 +333,19 @@ struct _GMainLoop | ||||
|   gint ref_count;  /* (atomic) */ | ||||
| }; | ||||
|  | ||||
| struct _GIdleSource | ||||
| { | ||||
|   GSource  source; | ||||
|   gboolean one_shot; | ||||
| }; | ||||
|  | ||||
| struct _GTimeoutSource | ||||
| { | ||||
|   GSource     source; | ||||
|   /* Measured in seconds if 'seconds' is TRUE, or milliseconds otherwise. */ | ||||
|   guint       interval; | ||||
|   gboolean    seconds; | ||||
|   gboolean    one_shot; | ||||
| }; | ||||
|  | ||||
| struct _GChildWatchSource | ||||
| @@ -4970,7 +4978,16 @@ g_timeout_dispatch (GSource     *source, | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   again = callback (user_data); | ||||
|   if (timeout_source->one_shot) | ||||
|     { | ||||
|       GSourceOnceFunc once_callback = (GSourceOnceFunc) callback; | ||||
|       once_callback (user_data); | ||||
|       again = G_SOURCE_REMOVE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       again = callback (user_data); | ||||
|     } | ||||
|  | ||||
|   TRACE (GLIB_TIMEOUT_DISPATCH (source, source->context, callback, user_data, again)); | ||||
|  | ||||
| @@ -4980,6 +4997,23 @@ g_timeout_dispatch (GSource     *source, | ||||
|   return again; | ||||
| } | ||||
|  | ||||
| static GSource * | ||||
| timeout_source_new (guint    interval, | ||||
|                     gboolean seconds, | ||||
|                     gboolean one_shot) | ||||
| { | ||||
|   GSource *source = g_source_new (&g_timeout_funcs, sizeof (GTimeoutSource)); | ||||
|   GTimeoutSource *timeout_source = (GTimeoutSource *)source; | ||||
|  | ||||
|   timeout_source->interval = interval; | ||||
|   timeout_source->seconds = seconds; | ||||
|   timeout_source->one_shot = one_shot; | ||||
|  | ||||
|   g_timeout_set_expiration (timeout_source, g_get_monotonic_time ()); | ||||
|  | ||||
|   return source; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_timeout_source_new: | ||||
|  * @interval: the timeout interval in milliseconds. | ||||
| @@ -4998,13 +5032,7 @@ g_timeout_dispatch (GSource     *source, | ||||
| GSource * | ||||
| g_timeout_source_new (guint interval) | ||||
| { | ||||
|   GSource *source = g_source_new (&g_timeout_funcs, sizeof (GTimeoutSource)); | ||||
|   GTimeoutSource *timeout_source = (GTimeoutSource *)source; | ||||
|  | ||||
|   timeout_source->interval = interval; | ||||
|   g_timeout_set_expiration (timeout_source, g_get_monotonic_time ()); | ||||
|  | ||||
|   return source; | ||||
|   return timeout_source_new (interval, FALSE, FALSE); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -5030,17 +5058,37 @@ g_timeout_source_new (guint interval) | ||||
| GSource * | ||||
| g_timeout_source_new_seconds (guint interval) | ||||
| { | ||||
|   GSource *source = g_source_new (&g_timeout_funcs, sizeof (GTimeoutSource)); | ||||
|   GTimeoutSource *timeout_source = (GTimeoutSource *)source; | ||||
|  | ||||
|   timeout_source->interval = interval; | ||||
|   timeout_source->seconds = TRUE; | ||||
|  | ||||
|   g_timeout_set_expiration (timeout_source, g_get_monotonic_time ()); | ||||
|  | ||||
|   return source; | ||||
|   return timeout_source_new (interval, TRUE, FALSE); | ||||
| } | ||||
|  | ||||
| static guint | ||||
| timeout_add_full (gint           priority, | ||||
|                   guint          interval, | ||||
|                   gboolean       seconds, | ||||
|                   gboolean       one_shot, | ||||
|                   GSourceFunc    function, | ||||
|                   gpointer       data, | ||||
|                   GDestroyNotify notify) | ||||
| { | ||||
|   GSource *source; | ||||
|   guint id; | ||||
|  | ||||
|   g_return_val_if_fail (function != NULL, 0); | ||||
|  | ||||
|   source = timeout_source_new (interval, seconds, one_shot); | ||||
|  | ||||
|   if (priority != G_PRIORITY_DEFAULT) | ||||
|     g_source_set_priority (source, priority); | ||||
|  | ||||
|   g_source_set_callback (source, function, data, notify); | ||||
|   id = g_source_attach (source, NULL); | ||||
|  | ||||
|   TRACE (GLIB_TIMEOUT_ADD (source, g_main_context_default (), id, priority, interval, function, data)); | ||||
|  | ||||
|   g_source_unref (source); | ||||
|  | ||||
|   return id; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_timeout_add_full: (rename-to g_timeout_add) | ||||
| @@ -5086,24 +5134,7 @@ g_timeout_add_full (gint           priority, | ||||
| 		    gpointer       data, | ||||
| 		    GDestroyNotify notify) | ||||
| { | ||||
|   GSource *source; | ||||
|   guint id; | ||||
|    | ||||
|   g_return_val_if_fail (function != NULL, 0); | ||||
|  | ||||
|   source = g_timeout_source_new (interval); | ||||
|  | ||||
|   if (priority != G_PRIORITY_DEFAULT) | ||||
|     g_source_set_priority (source, priority); | ||||
|  | ||||
|   g_source_set_callback (source, function, data, notify); | ||||
|   id = g_source_attach (source, NULL); | ||||
|  | ||||
|   TRACE (GLIB_TIMEOUT_ADD (source, g_main_context_default (), id, priority, interval, function, data)); | ||||
|  | ||||
|   g_source_unref (source); | ||||
|  | ||||
|   return id; | ||||
|   return timeout_add_full (priority, interval, FALSE, FALSE, function, data, notify); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -5157,27 +5188,6 @@ g_timeout_add (guint32        interval, | ||||
| 			     interval, function, data, NULL); | ||||
| } | ||||
|  | ||||
| typedef struct { | ||||
|   GSourceOnceFunc function; | ||||
|   gpointer data; | ||||
| } OnceData; | ||||
|  | ||||
| static void | ||||
| once_data_free (gpointer data) | ||||
| { | ||||
|   g_free (data); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| once_function (gpointer data) | ||||
| { | ||||
|   OnceData *once_data = data; | ||||
|  | ||||
|   once_data->function (once_data->data); | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_timeout_add_once: | ||||
|  * @interval: the time after which the function will be called, in | ||||
| @@ -5202,19 +5212,7 @@ g_timeout_add_once (guint32         interval, | ||||
|                     GSourceOnceFunc function, | ||||
|                     gpointer        data) | ||||
| { | ||||
|   OnceData *once_data; | ||||
|  | ||||
|   g_return_val_if_fail (function != NULL, 0); | ||||
|  | ||||
|   once_data = g_new (OnceData, 1); | ||||
|   once_data->function = function; | ||||
|   once_data->data = data; | ||||
|  | ||||
|   return g_timeout_add_full (G_PRIORITY_DEFAULT, | ||||
|                              interval, | ||||
|                              once_function, | ||||
|                              once_data, | ||||
|                              once_data_free); | ||||
|   return timeout_add_full (G_PRIORITY_DEFAULT, interval, FALSE, TRUE, (GSourceFunc) function, data, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -5985,6 +5983,7 @@ g_idle_dispatch (GSource    *source, | ||||
| 		 GSourceFunc callback, | ||||
| 		 gpointer    user_data) | ||||
| { | ||||
|   GIdleSource *idle_source = (GIdleSource *)source; | ||||
|   gboolean again; | ||||
|  | ||||
|   if (!callback) | ||||
| @@ -5994,13 +5993,41 @@ g_idle_dispatch (GSource    *source, | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   again = callback (user_data); | ||||
|   if (idle_source->one_shot) | ||||
|     { | ||||
|       GSourceOnceFunc once_callback = (GSourceOnceFunc) callback; | ||||
|       once_callback (user_data); | ||||
|       again = G_SOURCE_REMOVE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       again = callback (user_data); | ||||
|     } | ||||
|  | ||||
|   TRACE (GLIB_IDLE_DISPATCH (source, source->context, callback, user_data, again)); | ||||
|  | ||||
|   return again; | ||||
| } | ||||
|  | ||||
| static GSource * | ||||
| idle_source_new (gboolean one_shot) | ||||
| { | ||||
|   GSource *source; | ||||
|   GIdleSource *idle_source; | ||||
|  | ||||
|   source = g_source_new (&g_idle_funcs, sizeof (GIdleSource)); | ||||
|   idle_source = (GIdleSource *) source; | ||||
|  | ||||
|   idle_source->one_shot = one_shot; | ||||
|  | ||||
|   g_source_set_priority (source, G_PRIORITY_DEFAULT_IDLE); | ||||
|  | ||||
|   /* Set a default name on the source, just in case the caller does not. */ | ||||
|   g_source_set_static_name (source, "GIdleSource"); | ||||
|  | ||||
|   return source; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_idle_source_new: | ||||
|  *  | ||||
| @@ -6016,16 +6043,35 @@ g_idle_dispatch (GSource    *source, | ||||
|  **/ | ||||
| GSource * | ||||
| g_idle_source_new (void) | ||||
| { | ||||
|   return idle_source_new (FALSE); | ||||
| } | ||||
|  | ||||
| static guint | ||||
| idle_add_full (gint           priority, | ||||
|                gboolean       one_shot, | ||||
|                GSourceFunc    function, | ||||
|                gpointer       data, | ||||
|                GDestroyNotify notify) | ||||
| { | ||||
|   GSource *source; | ||||
|   guint id; | ||||
|  | ||||
|   source = g_source_new (&g_idle_funcs, sizeof (GSource)); | ||||
|   g_source_set_priority (source, G_PRIORITY_DEFAULT_IDLE); | ||||
|   g_return_val_if_fail (function != NULL, 0); | ||||
|  | ||||
|   /* Set a default name on the source, just in case the caller does not. */ | ||||
|   g_source_set_static_name (source, "GIdleSource"); | ||||
|   source = idle_source_new (one_shot); | ||||
|  | ||||
|   return source; | ||||
|   if (priority != G_PRIORITY_DEFAULT_IDLE) | ||||
|     g_source_set_priority (source, priority); | ||||
|  | ||||
|   g_source_set_callback (source, function, data, notify); | ||||
|   id = g_source_attach (source, NULL); | ||||
|  | ||||
|   TRACE (GLIB_IDLE_ADD (source, g_main_context_default (), id, priority, function, data)); | ||||
|  | ||||
|   g_source_unref (source); | ||||
|  | ||||
|   return id; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -6059,24 +6105,7 @@ g_idle_add_full (gint           priority, | ||||
| 		 gpointer       data, | ||||
| 		 GDestroyNotify notify) | ||||
| { | ||||
|   GSource *source; | ||||
|   guint id; | ||||
|    | ||||
|   g_return_val_if_fail (function != NULL, 0); | ||||
|  | ||||
|   source = g_idle_source_new (); | ||||
|  | ||||
|   if (priority != G_PRIORITY_DEFAULT_IDLE) | ||||
|     g_source_set_priority (source, priority); | ||||
|  | ||||
|   g_source_set_callback (source, function, data, notify); | ||||
|   id = g_source_attach (source, NULL); | ||||
|  | ||||
|   TRACE (GLIB_IDLE_ADD (source, g_main_context_default (), id, priority, function, data)); | ||||
|  | ||||
|   g_source_unref (source); | ||||
|  | ||||
|   return id; | ||||
|   return idle_add_full (priority, FALSE, function, data, notify); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -6130,15 +6159,7 @@ guint | ||||
| g_idle_add_once (GSourceOnceFunc function, | ||||
|                  gpointer        data) | ||||
| { | ||||
|   OnceData *once_data; | ||||
|  | ||||
|   g_return_val_if_fail (function != NULL, 0); | ||||
|  | ||||
|   once_data = g_new (OnceData, 1); | ||||
|   once_data->function = function; | ||||
|   once_data->data = data; | ||||
|  | ||||
|   return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, once_function, once_data, once_data_free); | ||||
|   return idle_add_full (G_PRIORITY_DEFAULT_IDLE, TRUE, (GSourceFunc) function, data, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
		Reference in New Issue
	
	Block a user