2.34.0
[platform/upstream/at-spi2-core.git] / registryd / reentrant-list.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 #include <config.h>
25 #include <glib.h>
26
27 #include "reentrant-list.h"
28
29 typedef struct {
30         GList **list;
31         GList  *iterator;
32 } Iteration;
33
34 static GSList *working_list = NULL; /* of Iteration */
35
36 /*
37  *   deletes an element from the list - in a re-entrant
38  * safe fashion; advances the element pointer to the next
39  * element.
40  */
41 void
42 spi_re_entrant_list_delete_link (GList * const *element_ptr)
43 {
44   GSList    *l;
45   GList     *next;
46   GList     *element;
47   gboolean   first_item;
48   GList *dummy G_GNUC_UNUSED;
49
50   g_return_if_fail (element_ptr != NULL);
51
52   element = *element_ptr;
53   g_return_if_fail (element != NULL);
54
55   next = element->next;
56   first_item = (element->prev == NULL);
57
58   dummy = g_list_remove_link (NULL, element);
59
60   for (l = working_list; l; l = l->next)
61     {
62        Iteration *i = l->data;
63
64        if (i->iterator == element)
65          {
66            i->iterator = next;
67          }
68
69        if (first_item && *(i->list) == element)
70          {
71            *(i->list) = next;
72          }
73     }
74
75   g_list_free_1 (element);
76 }
77
78 void
79 spi_re_entrant_list_foreach (GList         **list,
80                              SpiReEntrantFn  func,
81                              gpointer        user_data)
82 {
83         Iteration i;
84
85         if (!list || !*list)
86           {
87             return;
88           }
89
90         i.list = list;
91         i.iterator = *list;
92
93         working_list = g_slist_prepend (working_list, &i);
94
95         while (i.iterator) {
96                 GList *l = i.iterator;
97
98                 func (&i.iterator, user_data);
99
100                 if (i.iterator == l)
101                         i.iterator = i.iterator->next;
102         }
103
104         working_list = g_slist_remove (working_list, &i);
105 }