messenger-gtk

Gtk+3 graphical user interfaces for GNUnet Messenger
Log | Files | Refs | Submodules | README | LICENSE

util.c (4615B)


      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 <pthread.h>
     28 #include <stdio.h>
     29 
     30 static GList *tasks = NULL;
     31 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
     32 
     33 struct UTIL_CompleteTask
     34 {
     35   GSourceFunc function;
     36   gpointer data;
     37   guint id;
     38 };
     39 
     40 static void
     41 util_kill_task(gpointer task_data)
     42 {
     43   g_assert(task_data);
     44 
     45   struct UTIL_CompleteTask *task = (struct UTIL_CompleteTask*) task_data;
     46 
     47   if (task->id)
     48     g_source_remove(task->id);
     49 
     50   g_free(task);
     51 }
     52 
     53 void
     54 util_scheduler_cleanup()
     55 {
     56   if (tasks)
     57     g_list_free_full(tasks, (GDestroyNotify) util_kill_task);
     58 
     59   tasks = NULL;
     60 }
     61 
     62 static gboolean
     63 util_complete_task(gpointer task_data)
     64 {
     65   g_assert(task_data);
     66 
     67   struct UTIL_CompleteTask *task = (struct UTIL_CompleteTask*) task_data;
     68   gboolean result = FALSE;
     69 
     70   pthread_mutex_lock(&mutex);
     71   if (!tasks)
     72     goto unlock_mutex;
     73 
     74   const GSourceFunc function = task->function;
     75   gpointer data = task->data;
     76 
     77   if (tasks)
     78     tasks = g_list_remove(tasks, task);
     79 
     80   g_free(task);
     81 
     82   result = function(data);
     83 
     84 unlock_mutex:
     85   pthread_mutex_unlock(&mutex);
     86   return result;
     87 }
     88 
     89 guint
     90 util_idle_add(GSourceFunc function,
     91               gpointer data)
     92 {
     93   struct UTIL_CompleteTask *task = g_malloc(sizeof(struct UTIL_CompleteTask));
     94 
     95   task->function = function;
     96   task->data = data;
     97   task->id = g_idle_add(
     98     G_SOURCE_FUNC(util_complete_task),
     99     task
    100   );
    101 
    102   tasks = g_list_append(
    103     tasks,
    104     task
    105   );
    106 
    107   return task->id;
    108 }
    109 
    110 guint
    111 util_immediate_add(GSourceFunc function,
    112                    gpointer data)
    113 {
    114   struct UTIL_CompleteTask *task = g_malloc(sizeof(struct UTIL_CompleteTask));
    115 
    116   task->function = function;
    117   task->data = data;
    118   task->id = g_timeout_add(
    119     0,
    120     G_SOURCE_FUNC(util_complete_task),
    121     task
    122   );
    123 
    124   tasks = g_list_append(
    125     tasks,
    126     task
    127   );
    128 
    129   return task->id;
    130 }
    131 
    132 guint
    133 util_timeout_add(guint interval,
    134                  GSourceFunc function,
    135                  gpointer data)
    136 {
    137   struct UTIL_CompleteTask *task = g_malloc(sizeof(struct UTIL_CompleteTask));
    138 
    139   task->function = function;
    140   task->data = data;
    141   task->id = g_timeout_add(
    142     interval,
    143     G_SOURCE_FUNC(util_complete_task),
    144     task
    145   );
    146 
    147   tasks = g_list_append(
    148     tasks,
    149     task
    150   );
    151 
    152   return task->id;
    153 }
    154 
    155 guint
    156 util_timeout_add_seconds(guint interval,
    157                          GSourceFunc function,
    158                          gpointer data)
    159 {
    160   struct UTIL_CompleteTask *task = g_malloc(sizeof(struct UTIL_CompleteTask));
    161 
    162   task->function = function;
    163   task->data = data;
    164   task->id = g_timeout_add_seconds(
    165     interval,
    166     G_SOURCE_FUNC(util_complete_task),
    167     task
    168   );
    169 
    170   tasks = g_list_append(
    171     tasks,
    172     task
    173   );
    174 
    175   return task->id;
    176 }
    177 
    178 gboolean
    179 util_source_remove(guint tag)
    180 {
    181   struct UTIL_CompleteTask *task = NULL;
    182   GList *current = tasks;
    183 
    184   while (current)
    185   {
    186     task = (struct UTIL_CompleteTask*) current->data;
    187 
    188     if (task->id == tag)
    189       break;
    190 
    191     current = g_list_next(current);
    192     task = NULL;
    193   }
    194 
    195   if (!task)
    196     return FALSE;
    197 
    198   const gboolean result = g_source_remove(task->id);
    199 
    200   tasks = g_list_remove(tasks, task);
    201   g_free(task);
    202 
    203   return result;
    204 }
    205 
    206 gboolean
    207 util_source_remove_by_data(gpointer data)
    208 {
    209   struct UTIL_CompleteTask *task = NULL;
    210   GList *current = tasks;
    211   GList *matches = NULL;
    212 
    213   while (current)
    214   {
    215     task = (struct UTIL_CompleteTask*) current->data;
    216 
    217     if (task->data == data)
    218       matches = g_list_append(matches, task);
    219 
    220     current = g_list_next(current);
    221     task = NULL;
    222   }
    223 
    224   if (!matches)
    225     return FALSE;
    226 
    227   gboolean result = TRUE;
    228 
    229   current = matches;
    230   while (current)
    231   {
    232     task = (struct UTIL_CompleteTask*) current->data;
    233 
    234     result &= g_source_remove(task->id);
    235     tasks = g_list_remove(tasks, task);
    236     g_free(task);
    237 
    238     current = g_list_next(current);
    239   }
    240 
    241   g_list_free(matches);
    242   return result;
    243 }