aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/application.c39
-rw-r--r--src/event.c14
-rw-r--r--src/file.c8
-rw-r--r--src/meson.build2
-rw-r--r--src/request.c9
-rw-r--r--src/ui/accounts.c4
-rw-r--r--src/ui/chat.c18
-rw-r--r--src/ui/chat_entry.c4
-rw-r--r--src/ui/contacts.c2
-rw-r--r--src/ui/messenger.c6
-rw-r--r--src/ui/new_account.c2
-rw-r--r--src/ui/play_media.c16
-rw-r--r--src/ui/send_file.c8
-rw-r--r--src/util.c210
-rw-r--r--src/util.h46
15 files changed, 339 insertions, 49 deletions
diff --git a/src/application.c b/src/application.c
index f39a9b7..9b5fd54 100644
--- a/src/application.c
+++ b/src/application.c
@@ -87,7 +87,7 @@ _application_init(MESSENGER_Application *app)
87 if (app->chat.identity) 87 if (app->chat.identity)
88 application_show_window(app); 88 application_show_window(app);
89 else 89 else
90 app->init = g_idle_add(G_SOURCE_FUNC(_application_accounts), app); 90 app->init = util_idle_add(G_SOURCE_FUNC(_application_accounts), app);
91} 91}
92 92
93static void 93static void
@@ -639,7 +639,25 @@ application_call_event(MESSENGER_Application *app,
639 call->app = app; 639 call->app = app;
640 call->event = event; 640 call->event = event;
641 641
642 g_timeout_add(0, G_SOURCE_FUNC(_application_event_call), call); 642 util_idle_add(G_SOURCE_FUNC(_application_event_call), call);
643}
644
645static gboolean
646_application_sync_event_call(gpointer user_data)
647{
648 g_assert(user_data);
649
650 MESSENGER_ApplicationEventCall *call;
651
652 call = (MESSENGER_ApplicationEventCall*) user_data;
653
654 call->event(call->app);
655 util_scheduler_cleanup();
656
657 pthread_mutex_unlock(&(call->app->chat.mutex));
658
659 GNUNET_free(call);
660 return FALSE;
643} 661}
644 662
645void 663void
@@ -648,7 +666,20 @@ application_call_sync_event(MESSENGER_Application *app,
648{ 666{
649 g_assert((app) && (event)); 667 g_assert((app) && (event));
650 668
651 event(app); 669 MESSENGER_ApplicationEventCall *call;
670
671 call = (MESSENGER_ApplicationEventCall*) GNUNET_malloc(
672 sizeof(MESSENGER_ApplicationEventCall)
673 );
674
675 call->app = app;
676 call->event = event;
677
678 util_scheduler_cleanup();
679 util_idle_add(G_SOURCE_FUNC(_application_sync_event_call), call);
680
681 // Locking the mutex for synchronization
682 pthread_mutex_lock(&(app->chat.mutex));
652} 683}
653 684
654typedef struct MESSENGER_ApplicationMessageEventCall 685typedef struct MESSENGER_ApplicationMessageEventCall
@@ -698,7 +729,7 @@ application_call_message_event(MESSENGER_Application *app,
698 call->context = context; 729 call->context = context;
699 call->message = message; 730 call->message = message;
700 731
701 g_idle_add(G_SOURCE_FUNC(_application_message_event_call), call); 732 util_idle_add(G_SOURCE_FUNC(_application_message_event_call), call);
702} 733}
703 734
704void 735void
diff --git a/src/event.c b/src/event.c
index 0df6a74..ce81f7f 100644
--- a/src/event.c
+++ b/src/event.c
@@ -142,10 +142,10 @@ event_refresh_accounts(MESSENGER_Application *app)
142 g_assert(app); 142 g_assert(app);
143 143
144 if (app->ui.messenger.account_refresh) 144 if (app->ui.messenger.account_refresh)
145 g_source_remove(app->ui.messenger.account_refresh); 145 util_source_remove(app->ui.messenger.account_refresh);
146 146
147 if (app->ui.messenger.main_window) 147 if (app->ui.messenger.main_window)
148 app->ui.messenger.account_refresh = g_idle_add( 148 app->ui.messenger.account_refresh = util_idle_add(
149 G_SOURCE_FUNC(_idle_refresh_accounts), 149 G_SOURCE_FUNC(_idle_refresh_accounts),
150 app 150 app
151 ); 151 );
@@ -217,9 +217,9 @@ enqueue_chat_entry_update(UI_CHAT_ENTRY_Handle *entry)
217 g_assert(entry); 217 g_assert(entry);
218 218
219 if (entry->update) 219 if (entry->update)
220 g_source_remove(entry->update); 220 util_source_remove(entry->update);
221 221
222 entry->update = g_idle_add( 222 entry->update = util_idle_add(
223 G_SOURCE_FUNC(_idle_chat_entry_update), 223 G_SOURCE_FUNC(_idle_chat_entry_update),
224 entry 224 entry
225 ); 225 );
@@ -261,9 +261,9 @@ _add_new_chat_entry(MESSENGER_Application *app,
261 ); 261 );
262 262
263 if (ui->chat_selection) 263 if (ui->chat_selection)
264 g_source_remove(ui->chat_selection); 264 util_source_remove(ui->chat_selection);
265 265
266 ui->chat_selection = g_idle_add( 266 ui->chat_selection = util_idle_add(
267 G_SOURCE_FUNC(_select_chat_to_activate), 267 G_SOURCE_FUNC(_select_chat_to_activate),
268 entry 268 entry
269 ); 269 );
@@ -440,7 +440,7 @@ event_update_chats(MESSENGER_Application *app,
440 enqueue_chat_entry_update(handle); 440 enqueue_chat_entry_update(handle);
441 441
442 if (app->settings.leave_chats_delay > 0) 442 if (app->settings.leave_chats_delay > 0)
443 g_timeout_add_seconds( 443 util_timeout_add_seconds(
444 app->settings.leave_chats_delay, 444 app->settings.leave_chats_delay,
445 _delayed_context_drop, 445 _delayed_context_drop,
446 context 446 context
diff --git a/src/file.c b/src/file.c
index 21862b4..cb89012 100644
--- a/src/file.c
+++ b/src/file.c
@@ -64,7 +64,7 @@ file_destroy_info(struct GNUNET_CHAT_File *file)
64 file_unload_preview_image(file); 64 file_unload_preview_image(file);
65 65
66 if (info->update_task) 66 if (info->update_task)
67 g_source_remove(info->update_task); 67 util_source_remove(info->update_task);
68 68
69 if (info->file_messages) 69 if (info->file_messages)
70 g_list_free(info->file_messages); 70 g_list_free(info->file_messages);
@@ -202,7 +202,7 @@ file_update_download_info(const struct GNUNET_CHAT_File *file,
202 return; 202 return;
203 203
204 info->app = app; 204 info->app = app;
205 info->update_task = g_idle_add(file_update_messages, info); 205 info->update_task = util_idle_add(file_update_messages, info);
206} 206}
207 207
208static void 208static void
@@ -269,7 +269,7 @@ file_unload_preview_image(const struct GNUNET_CHAT_File *file)
269 269
270 if (info->redraw_animation_task) 270 if (info->redraw_animation_task)
271 { 271 {
272 g_source_remove(info->redraw_animation_task); 272 util_source_remove(info->redraw_animation_task);
273 info->redraw_animation_task = 0; 273 info->redraw_animation_task = 0;
274 } 274 }
275 275
@@ -328,7 +328,7 @@ file_get_current_preview_image(const struct GNUNET_CHAT_File *file)
328 info->preview_animation_iter 328 info->preview_animation_iter
329 ); 329 );
330 330
331 info->redraw_animation_task = g_timeout_add( 331 info->redraw_animation_task = util_timeout_add(
332 delay, file_redraw_animation, info 332 delay, file_redraw_animation, info
333 ); 333 );
334 } 334 }
diff --git a/src/meson.build b/src/meson.build
index 46b7b4b..509ddfb 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -29,6 +29,6 @@ messenger_gtk_sources = files([
29 'request.c', 'request.h', 29 'request.c', 'request.h',
30 'resources.c', 'resources.h', 30 'resources.c', 'resources.h',
31 'ui.c', 'ui.h', 31 'ui.c', 'ui.h',
32 'util.h', 32 'util.c', 'util.h',
33 'messenger_gtk.c', 33 'messenger_gtk.c',
34]) + messenger_gtk_chat_sources + messenger_gtk_ui_sources 34]) + messenger_gtk_chat_sources + messenger_gtk_ui_sources
diff --git a/src/request.c b/src/request.c
index d6a5ea7..6ed3ca4 100644
--- a/src/request.c
+++ b/src/request.c
@@ -64,8 +64,9 @@ request_new(MESSENGER_Application *application,
64 request->user_data = user_data; 64 request->user_data = user_data;
65 65
66#ifdef MESSENGER_APPLICATION_NO_PORTAL 66#ifdef MESSENGER_APPLICATION_NO_PORTAL
67 request->timeout = g_timeout_add( 67 request->timeout = util_idle_add(
68 0, G_SOURCE_FUNC(_request_timeout_call), request 68 G_SOURCE_FUNC(_request_timeout_call),
69 request
69 ); 70 );
70#endif 71#endif
71 72
@@ -228,7 +229,7 @@ request_cancel(MESSENGER_Request *request)
228 229
229#ifdef MESSENGER_APPLICATION_NO_PORTAL 230#ifdef MESSENGER_APPLICATION_NO_PORTAL
230 if (request->timeout) 231 if (request->timeout)
231 g_source_remove(request->timeout); 232 util_source_remove(request->timeout);
232 233
233 request->timeout = 0; 234 request->timeout = 0;
234#endif 235#endif
@@ -247,7 +248,7 @@ request_cleanup(MESSENGER_Request *request)
247 248
248#ifdef MESSENGER_APPLICATION_NO_PORTAL 249#ifdef MESSENGER_APPLICATION_NO_PORTAL
249 if (request->timeout) 250 if (request->timeout)
250 g_source_remove(request->timeout); 251 util_source_remove(request->timeout);
251 252
252 request->timeout = 0; 253 request->timeout = 0;
253#endif 254#endif
diff --git a/src/ui/accounts.c b/src/ui/accounts.c
index e0db9e4..82a94d1 100644
--- a/src/ui/accounts.c
+++ b/src/ui/accounts.c
@@ -77,7 +77,7 @@ handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
77 // Drop activations of rows which do not contain accounts 77 // Drop activations of rows which do not contain accounts
78 if (!gtk_list_box_row_get_selectable(row)) 78 if (!gtk_list_box_row_get_selectable(row))
79 { 79 {
80 app->ui.accounts.show_queued = g_idle_add( 80 app->ui.accounts.show_queued = util_idle_add(
81 G_SOURCE_FUNC(_open_new_account_dialog), app 81 G_SOURCE_FUNC(_open_new_account_dialog), app
82 ); 82 );
83 83
@@ -93,7 +93,7 @@ handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
93 93
94 // Handle the GUI swap asyncronously 94 // Handle the GUI swap asyncronously
95 if (!gtk_widget_is_visible(GTK_WIDGET(app->ui.messenger.main_window))) 95 if (!gtk_widget_is_visible(GTK_WIDGET(app->ui.messenger.main_window)))
96 app->ui.accounts.show_queued = g_idle_add( 96 app->ui.accounts.show_queued = util_idle_add(
97 G_SOURCE_FUNC(_show_messenger_main_window), app 97 G_SOURCE_FUNC(_show_messenger_main_window), app
98 ); 98 );
99 99
diff --git a/src/ui/chat.c b/src/ui/chat.c
index 0cd85da..4bcded4 100644
--- a/src/ui/chat.c
+++ b/src/ui/chat.c
@@ -72,7 +72,7 @@ handle_chat_details_via_button_click(UNUSED GtkButton* button,
72 UI_CHAT_Handle *handle = (UI_CHAT_Handle*) user_data; 72 UI_CHAT_Handle *handle = (UI_CHAT_Handle*) user_data;
73 73
74 gtk_widget_set_sensitive(GTK_WIDGET(handle->messages_listbox), FALSE); 74 gtk_widget_set_sensitive(GTK_WIDGET(handle->messages_listbox), FALSE);
75 g_idle_add( 75 util_idle_add(
76 G_SOURCE_FUNC(_flap_chat_details_reveal_switch), 76 G_SOURCE_FUNC(_flap_chat_details_reveal_switch),
77 handle 77 handle
78 ); 78 );
@@ -1092,7 +1092,7 @@ _stop_playing_recording(UI_CHAT_Handle *handle,
1092 1092
1093 if (handle->play_timer) 1093 if (handle->play_timer)
1094 { 1094 {
1095 g_source_remove(handle->play_timer); 1095 util_source_remove(handle->play_timer);
1096 handle->play_timer = 0; 1096 handle->play_timer = 0;
1097 } 1097 }
1098} 1098}
@@ -1197,7 +1197,7 @@ _record_timer_func(gpointer user_data)
1197 if (!(handle->recorded)) 1197 if (!(handle->recorded))
1198 { 1198 {
1199 handle->record_time++; 1199 handle->record_time++;
1200 handle->record_timer = g_timeout_add_seconds( 1200 handle->record_timer = util_timeout_add_seconds(
1201 1, 1201 1,
1202 _record_timer_func, 1202 _record_timer_func,
1203 handle 1203 handle
@@ -1230,7 +1230,7 @@ _play_timer_func(gpointer user_data)
1230 if (handle->playing) 1230 if (handle->playing)
1231 { 1231 {
1232 handle->play_time++; 1232 handle->play_time++;
1233 handle->play_timer = g_timeout_add( 1233 handle->play_timer = util_timeout_add(
1234 10, 1234 10,
1235 _play_timer_func, 1235 _play_timer_func,
1236 handle 1236 handle
@@ -1256,8 +1256,7 @@ handle_record_bus_watch(UNUSED GstBus *bus,
1256 { 1256 {
1257 case GST_MESSAGE_STREAM_START: 1257 case GST_MESSAGE_STREAM_START:
1258 handle->record_time = 0; 1258 handle->record_time = 0;
1259 handle->record_timer = g_timeout_add_seconds( 1259 handle->record_timer = util_idle_add(
1260 0,
1261 _record_timer_func, 1260 _record_timer_func,
1262 handle 1261 handle
1263 ); 1262 );
@@ -1282,8 +1281,7 @@ handle_play_bus_watch(UNUSED GstBus *bus,
1282 { 1281 {
1283 case GST_MESSAGE_STREAM_START: 1282 case GST_MESSAGE_STREAM_START:
1284 handle->play_time = 0; 1283 handle->play_time = 0;
1285 handle->play_timer = g_timeout_add_seconds( 1284 handle->play_timer = util_idle_add(
1286 0,
1287 _play_timer_func, 1285 _play_timer_func,
1288 handle 1286 handle
1289 ); 1287 );
@@ -2320,10 +2318,10 @@ ui_chat_delete(UI_CHAT_Handle *handle)
2320 remove(handle->recording_filename); 2318 remove(handle->recording_filename);
2321 2319
2322 if (handle->record_timer) 2320 if (handle->record_timer)
2323 g_source_remove(handle->record_timer); 2321 util_source_remove(handle->record_timer);
2324 2322
2325 if (handle->play_timer) 2323 if (handle->play_timer)
2326 g_source_remove(handle->play_timer); 2324 util_source_remove(handle->play_timer);
2327 2325
2328 g_free(handle); 2326 g_free(handle);
2329} 2327}
diff --git a/src/ui/chat_entry.c b/src/ui/chat_entry.c
index 98e9a6b..e7f945e 100644
--- a/src/ui/chat_entry.c
+++ b/src/ui/chat_entry.c
@@ -242,7 +242,7 @@ ui_chat_entry_delete(UI_CHAT_ENTRY_Handle *handle)
242 g_object_unref(handle->builder); 242 g_object_unref(handle->builder);
243 243
244 if (handle->update) 244 if (handle->update)
245 g_source_remove(handle->update); 245 util_source_remove(handle->update);
246 246
247 g_free(handle); 247 g_free(handle);
248} 248}
@@ -255,6 +255,8 @@ ui_chat_entry_dispose(UI_CHAT_ENTRY_Handle *handle,
255 255
256 UI_MESSENGER_Handle *ui = &(app->ui.messenger); 256 UI_MESSENGER_Handle *ui = &(app->ui.messenger);
257 257
258 util_source_remove_by_data(handle);
259
258 ui->chat_entries = g_list_remove(ui->chat_entries, handle); 260 ui->chat_entries = g_list_remove(ui->chat_entries, handle);
259 261
260 gtk_container_remove( 262 gtk_container_remove(
diff --git a/src/ui/contacts.c b/src/ui/contacts.c
index e482cd6..6be1bd6 100644
--- a/src/ui/contacts.c
+++ b/src/ui/contacts.c
@@ -62,7 +62,7 @@ handle_contacts_listbox_row_activated(UNUSED GtkListBox* listbox,
62 62
63 if (!gtk_list_box_row_get_selectable(row)) 63 if (!gtk_list_box_row_get_selectable(row))
64 { 64 {
65 g_idle_add(G_SOURCE_FUNC(_open_new_contact_dialog), app); 65 util_idle_add(G_SOURCE_FUNC(_open_new_contact_dialog), app);
66 goto close_dialog; 66 goto close_dialog;
67 } 67 }
68 68
diff --git a/src/ui/messenger.c b/src/ui/messenger.c
index 65f4d46..30b0b39 100644
--- a/src/ui/messenger.c
+++ b/src/ui/messenger.c
@@ -85,7 +85,7 @@ handle_user_details_via_button_click(UNUSED GtkButton* button,
85 85
86 gtk_widget_set_sensitive(GTK_WIDGET(handle->chats_search), FALSE); 86 gtk_widget_set_sensitive(GTK_WIDGET(handle->chats_search), FALSE);
87 gtk_widget_set_sensitive(GTK_WIDGET(handle->chats_listbox), FALSE); 87 gtk_widget_set_sensitive(GTK_WIDGET(handle->chats_listbox), FALSE);
88 g_idle_add( 88 util_idle_add(
89 G_SOURCE_FUNC(_flap_user_details_reveal_switch), 89 G_SOURCE_FUNC(_flap_user_details_reveal_switch),
90 handle 90 handle
91 ); 91 );
@@ -801,10 +801,10 @@ ui_messenger_cleanup(UI_MESSENGER_Handle *handle)
801 g_list_free_full(handle->chat_entries, (GDestroyNotify) ui_chat_entry_delete); 801 g_list_free_full(handle->chat_entries, (GDestroyNotify) ui_chat_entry_delete);
802 802
803 if (handle->chat_selection) 803 if (handle->chat_selection)
804 g_source_remove(handle->chat_selection); 804 util_source_remove(handle->chat_selection);
805 805
806 if (handle->account_refresh) 806 if (handle->account_refresh)
807 g_source_remove(handle->account_refresh); 807 util_source_remove(handle->account_refresh);
808 808
809 memset(handle, 0, sizeof(*handle)); 809 memset(handle, 0, sizeof(*handle));
810} 810}
diff --git a/src/ui/new_account.c b/src/ui/new_account.c
index 2426c70..086edd8 100644
--- a/src/ui/new_account.c
+++ b/src/ui/new_account.c
@@ -57,7 +57,7 @@ _open_new_account(GtkEntry *entry,
57 app->chat.identity = GNUNET_strdup(name); 57 app->chat.identity = GNUNET_strdup(name);
58 58
59 if (!gtk_widget_is_visible(GTK_WIDGET(app->ui.messenger.main_window))) 59 if (!gtk_widget_is_visible(GTK_WIDGET(app->ui.messenger.main_window)))
60 app->ui.new_account.show_queued = g_idle_add( 60 app->ui.new_account.show_queued = util_idle_add(
61 G_SOURCE_FUNC(_show_messenger_main_window), app 61 G_SOURCE_FUNC(_show_messenger_main_window), app
62 ); 62 );
63} 63}
diff --git a/src/ui/play_media.c b/src/ui/play_media.c
index 4540f3e..880e405 100644
--- a/src/ui/play_media.c
+++ b/src/ui/play_media.c
@@ -196,11 +196,11 @@ _set_timeout_callback_of_timeline(UI_PLAY_MEDIA_Handle *handle,
196 g_assert(handle); 196 g_assert(handle);
197 197
198 if (handle->timeline) 198 if (handle->timeline)
199 g_source_remove(handle->timeline); 199 util_source_remove(handle->timeline);
200 200
201 if (connected) 201 if (connected)
202 handle->timeline = g_timeout_add( 202 handle->timeline = util_timeout_add_seconds(
203 1000, 203 1,
204 G_SOURCE_FUNC(_adjust_playing_media_position), 204 G_SOURCE_FUNC(_adjust_playing_media_position),
205 handle 205 handle
206 ); 206 );
@@ -399,7 +399,7 @@ handle_fullscreen_button_click(GtkButton *button,
399 else 399 else
400 { 400 {
401 if (handle->motion_lost) 401 if (handle->motion_lost)
402 g_source_remove(handle->motion_lost); 402 util_source_remove(handle->motion_lost);
403 403
404 handle->motion_lost = 0; 404 handle->motion_lost = 0;
405 } 405 }
@@ -434,14 +434,14 @@ handle_media_motion_notify(GtkWidget *widget,
434 return FALSE; 434 return FALSE;
435 435
436 if (handle->motion_lost) 436 if (handle->motion_lost)
437 g_source_remove(handle->motion_lost); 437 util_source_remove(handle->motion_lost);
438 438
439 hdy_flap_set_reveal_flap(handle->controls_flap, TRUE); 439 hdy_flap_set_reveal_flap(handle->controls_flap, TRUE);
440 440
441 if (!(handle->fullscreen)) 441 if (!(handle->fullscreen))
442 return FALSE; 442 return FALSE;
443 443
444 handle->motion_lost = g_timeout_add_seconds( 444 handle->motion_lost = util_timeout_add_seconds(
445 3, 445 3,
446 G_SOURCE_FUNC(handle_media_motion_lost), 446 G_SOURCE_FUNC(handle_media_motion_lost),
447 handle 447 handle
@@ -841,10 +841,10 @@ ui_play_media_window_cleanup(UI_PLAY_MEDIA_Handle *handle)
841 g_object_unref(handle->builder); 841 g_object_unref(handle->builder);
842 842
843 if (handle->timeline) 843 if (handle->timeline)
844 g_source_remove(handle->timeline); 844 util_source_remove(handle->timeline);
845 845
846 if (handle->motion_lost) 846 if (handle->motion_lost)
847 g_source_remove(handle->motion_lost); 847 util_source_remove(handle->motion_lost);
848 848
849 if (handle->pipeline) 849 if (handle->pipeline)
850 { 850 {
diff --git a/src/ui/send_file.c b/src/ui/send_file.c
index f8429bc..e737fdf 100644
--- a/src/ui/send_file.c
+++ b/src/ui/send_file.c
@@ -186,8 +186,10 @@ handle_file_drawing_area_draw(GtkWidget* drawing_area,
186 handle->animation_iter 186 handle->animation_iter
187 ); 187 );
188 188
189 handle->redraw_animation = g_timeout_add( 189 handle->redraw_animation = util_timeout_add(
190 delay, handle_file_redraw_animation, handle 190 delay,
191 handle_file_redraw_animation,
192 handle
191 ); 193 );
192 194
193render_image: 195render_image:
@@ -241,7 +243,7 @@ _clear_file_preview_data(UI_SEND_FILE_Handle *handle)
241 243
242 if (handle->redraw_animation) 244 if (handle->redraw_animation)
243 { 245 {
244 g_source_remove(handle->redraw_animation); 246 util_source_remove(handle->redraw_animation);
245 handle->redraw_animation = 0; 247 handle->redraw_animation = 0;
246 } 248 }
247 249
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..bf9e7d0
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,210 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2024 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file util.c
23 */
24
25#include "util.h"
26
27#include <stdio.h>
28
29static GList *tasks = NULL;
30
31struct UTIL_CompleteTask
32{
33 GSourceFunc function;
34 gpointer data;
35 guint id;
36};
37
38static void
39util_kill_task(gpointer task_data)
40{
41 g_assert(task_data);
42
43 struct UTIL_CompleteTask *task = (struct UTIL_CompleteTask*) task_data;
44
45 if (task->id)
46 g_source_remove(task->id);
47
48 g_free(task);
49}
50
51void
52util_scheduler_cleanup()
53{
54 if (tasks)
55 g_list_free_full(tasks, (GDestroyNotify) util_kill_task);
56
57 tasks = NULL;
58}
59
60static gboolean
61util_complete_task(gpointer task_data)
62{
63 g_assert(task_data);
64
65 struct UTIL_CompleteTask *task = (struct UTIL_CompleteTask*) task_data;
66
67 const GSourceFunc function = task->function;
68 gpointer data = task->data;
69
70 if (tasks)
71 tasks = g_list_remove(tasks, task);
72
73 g_free(task);
74
75 return function(data);
76}
77
78guint
79util_idle_add(GSourceFunc function,
80 gpointer data)
81{
82 struct UTIL_CompleteTask *task = g_malloc(sizeof(struct UTIL_CompleteTask));
83
84 task->function = function;
85 task->data = data;
86 task->id = g_idle_add(
87 G_SOURCE_FUNC(util_complete_task),
88 task
89 );
90
91 tasks = g_list_append(
92 tasks,
93 task
94 );
95
96 return task->id;
97}
98
99guint
100util_timeout_add(guint interval,
101 GSourceFunc function,
102 gpointer data)
103{
104 struct UTIL_CompleteTask *task = g_malloc(sizeof(struct UTIL_CompleteTask));
105
106 task->function = function;
107 task->data = data;
108 task->id = g_timeout_add(
109 interval,
110 G_SOURCE_FUNC(util_complete_task),
111 task
112 );
113
114 tasks = g_list_append(
115 tasks,
116 task
117 );
118
119 return task->id;
120}
121
122guint
123util_timeout_add_seconds(guint interval,
124 GSourceFunc function,
125 gpointer data)
126{
127 struct UTIL_CompleteTask *task = g_malloc(sizeof(struct UTIL_CompleteTask));
128
129 task->function = function;
130 task->data = data;
131 task->id = g_timeout_add_seconds(
132 interval,
133 G_SOURCE_FUNC(util_complete_task),
134 task
135 );
136
137 tasks = g_list_append(
138 tasks,
139 task
140 );
141
142 return task->id;
143}
144
145gboolean
146util_source_remove(guint tag)
147{
148 struct UTIL_CompleteTask *task = NULL;
149 GList *current = tasks;
150
151 while (current)
152 {
153 task = (struct UTIL_CompleteTask*) current->data;
154
155 if (task->id == tag)
156 break;
157
158 current = g_list_next(current);
159 task = NULL;
160 }
161
162 if (!task)
163 return FALSE;
164
165 const gboolean result = g_source_remove(task->id);
166
167 tasks = g_list_remove(tasks, task);
168 g_free(task);
169
170 return result;
171}
172
173gboolean
174util_source_remove_by_data(gpointer data)
175{
176 struct UTIL_CompleteTask *task = NULL;
177 GList *current = tasks;
178 GList *matches = NULL;
179
180 while (current)
181 {
182 task = (struct UTIL_CompleteTask*) current->data;
183
184 if (task->data == data)
185 matches = g_list_append(matches, task);
186
187 current = g_list_next(current);
188 task = NULL;
189 }
190
191 if (!matches)
192 return FALSE;
193
194 gboolean result = TRUE;
195
196 current = matches;
197 while (current)
198 {
199 task = (struct UTIL_CompleteTask*) current->data;
200
201 result &= g_source_remove(task->id);
202 tasks = g_list_remove(tasks, task);
203 g_free(task);
204
205 current = g_list_next(current);
206 }
207
208 g_list_free(matches);
209 return result;
210}
diff --git a/src/util.h b/src/util.h
index 3e566c8..290918a 100644
--- a/src/util.h
+++ b/src/util.h
@@ -36,4 +36,50 @@
36 ) \ 36 ) \
37) 37)
38 38
39/**
40 * Cancel all open asynchronous tasks.
41 */
42void
43util_scheduler_cleanup();
44
45/**
46 * Abstraction of `g_idle_add()` task
47 * to be cancelled externally.
48 */
49guint
50util_idle_add(GSourceFunc function,
51 gpointer data);
52
53/**
54 * Abstraction of `g_timeout_add()` task
55 * to be cancelled externally.
56 */
57guint
58util_timeout_add(guint interval,
59 GSourceFunc function,
60 gpointer data);
61
62/**
63 * Abstraction of `g_timeout_add_seconds()` task
64 * to be cancelled externally.
65 */
66guint
67util_timeout_add_seconds(guint interval,
68 GSourceFunc function,
69 gpointer data);
70
71/**
72 * Abstraction of `g_source_remove()` to
73 * cancel a task by its tag.
74 */
75gboolean
76util_source_remove(guint tag);
77
78/**
79 * Abstraction of `g_source_remove_by_userdata()` to
80 * cancel a task by its data.
81 */
82gboolean
83util_source_remove_by_data(gpointer data);
84
39#endif /* UTIL_H_ */ 85#endif /* UTIL_H_ */