source: trunk/third/gnome-vfs/libgnomevfs/gnome-vfs-messages.c @ 15497

Revision 15497, 7.6 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15496, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* gnome-vfs-messages.c - Status message reporting for GNOME Virtual File
3   System.
4
5   Copyright (C) 1999 Free Software Foundation
6
7   The Gnome Library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Library General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11
12   The Gnome Library is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   Library General Public License for more details.
16
17   You should have received a copy of the GNU Library General Public
18   License along with the Gnome Library; see the file COPYING.LIB.  If not,
19   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20   Boston, MA 02111-1307, USA.
21
22   Author: Havoc Pennington <hp@redhat.com> */
23
24#include "gnome-vfs-messages.h"
25
26#include <stdio.h>
27
28#ifdef G_THREADS_ENABLED
29#define MUTEX_LOCK(a)   if ((a) != NULL) g_mutex_lock (a)
30#define MUTEX_UNLOCK(a) if ((a) != NULL) g_mutex_unlock (a)
31#else
32#define MUTEX_LOCK(a)
33#define MUTEX_UNLOCK(a)
34#endif
35
36static guint next_id = 1;
37
38G_LOCK_DEFINE_STATIC (next_id);
39
40typedef struct Callback Callback;
41
42struct Callback {
43        GnomeVFSStatusCallback callback_func;
44        gpointer user_data;
45        GDestroyNotify notify_func;
46        guint id;
47};
48
49static Callback*
50callback_new (GnomeVFSStatusCallback callback_func,
51              gpointer user_data,
52              GDestroyNotify notify_func)
53{
54        Callback *cb;
55       
56        cb = g_new(Callback, 1);
57
58        cb->callback_func = callback_func;
59        cb->user_data = user_data;
60        cb->notify_func = notify_func;
61
62        G_LOCK(next_id);
63        cb->id = next_id;
64        ++next_id;
65        G_UNLOCK(next_id);
66
67        return cb;
68}
69
70static void
71callback_destroy (Callback *cb)
72{
73        if (cb->notify_func != NULL) {
74                (* cb->notify_func) (cb->user_data);
75        }
76
77        g_free(cb);
78}
79
80static void
81callback_invoke (Callback *cb, const gchar* message)
82{
83        if (cb->callback_func) {
84                (* cb->callback_func) (message, cb->user_data);
85        }
86}
87
88struct GnomeVFSMessageCallbacks {
89        GSList *list;
90#ifdef G_THREADS_ENABLED
91        GMutex *list_mutex;
92#endif
93};
94
95GnomeVFSMessageCallbacks*
96gnome_vfs_message_callbacks_new (void)
97{
98        GnomeVFSMessageCallbacks *cbs;
99
100        cbs = g_new0(GnomeVFSMessageCallbacks, 1);
101
102#ifdef G_THREADS_ENABLED
103        if (g_thread_supported ())
104                cbs->list_mutex = g_mutex_new ();
105        else
106                cbs->list_mutex = NULL;
107#endif
108       
109        return cbs;
110}
111
112void
113gnome_vfs_message_callbacks_destroy (GnomeVFSMessageCallbacks *cbs)
114{
115        GSList *tmp;
116
117        MUTEX_LOCK(cbs->list_mutex);
118       
119        tmp = cbs->list;
120
121        while (tmp != NULL) {
122                Callback *cb;
123
124                cb = tmp->data;
125
126                callback_destroy (cb);
127               
128                tmp = g_slist_next (tmp);
129        }
130       
131        g_slist_free (cbs->list);
132
133        MUTEX_UNLOCK(cbs->list_mutex);
134       
135#ifdef G_THREADS_ENABLED
136        if (cbs->list_mutex != NULL)
137                g_mutex_free (cbs->list_mutex);
138#endif
139       
140        g_free(cbs);
141}
142
143guint
144gnome_vfs_message_callbacks_add (GnomeVFSMessageCallbacks *cbs,
145                                 GnomeVFSStatusCallback    callback,
146                                 gpointer                  user_data)
147{
148        return gnome_vfs_message_callbacks_add_full (cbs, callback, user_data, NULL);
149}
150
151guint
152gnome_vfs_message_callbacks_add_full (GnomeVFSMessageCallbacks *cbs,
153                                      GnomeVFSStatusCallback    callback,
154                                      gpointer                  user_data,
155                                      GDestroyNotify            notify)
156{
157        Callback *cb;
158
159        cb = callback_new (callback, user_data, notify);
160
161        MUTEX_LOCK(cbs->list_mutex);
162       
163        cbs->list = g_slist_prepend (cbs->list, cb);
164
165        MUTEX_UNLOCK(cbs->list_mutex);
166       
167        return cb->id;
168}
169
170typedef gboolean (* MyGSListFilterFunc) (gpointer list_element, gpointer user_data);
171
172static GSList*
173my_g_slist_filter (GSList* list, MyGSListFilterFunc func, gpointer user_data)
174{
175        GSList *iter;
176        GSList *retval;
177
178        retval = NULL;
179        iter = list;
180
181        while (iter != NULL) {
182                GSList *freeme;
183               
184                if ((*func)(iter->data, user_data)) {
185                        retval = g_slist_prepend (retval, iter->data);
186                }
187               
188                freeme = iter;
189                iter = g_slist_next (iter);
190
191                g_assert(freeme != NULL);
192
193                /* Avoids using double the amount of space; glib can
194                   recycle these nodes into the new list */
195                g_slist_free_1 (freeme);
196        }
197
198        /* We assembled the nodes backward */
199        retval = g_slist_reverse (retval);
200       
201        return retval;
202}
203
204static gboolean
205callback_equal_predicate (gpointer callback, gpointer func)
206{
207        return !(((Callback*)callback)->callback_func ==
208                ((GnomeVFSStatusCallback)func));
209}
210
211static gboolean
212data_equal_predicate (gpointer callback, gpointer data)
213{
214        return !(((Callback*)callback)->user_data == data);
215}
216
217struct func_and_data {
218        GnomeVFSStatusCallback func;
219        gpointer data;
220};
221
222static gboolean
223all_equal_predicate (gpointer callback, gpointer func_and_data)
224{
225        Callback *cb = callback;
226        struct func_and_data* fd = func_and_data;
227
228        return !(cb->callback_func == fd->func && cb->user_data == fd->data);
229}
230
231void gnome_vfs_message_callbacks_remove (GnomeVFSMessageCallbacks *cbs,
232                                         guint num)
233{
234        GSList *iter;
235
236        MUTEX_LOCK(cbs->list_mutex);
237       
238        iter = cbs->list;
239
240        while (iter != NULL) {
241                Callback *cb;
242
243                cb = iter->data;
244
245                if (cb->id == num)
246                        break;
247                       
248                iter = g_slist_next (iter);
249        }
250
251        if (iter)
252                cbs->list = g_slist_remove(cbs->list, iter->data);
253        else
254                g_warning("status callback %u not found to remove", num);
255
256        MUTEX_UNLOCK(cbs->list_mutex);
257}
258
259void
260gnome_vfs_message_callbacks_remove_by_func (GnomeVFSMessageCallbacks *cbs,
261                                            GnomeVFSStatusCallback    callback)
262{
263        MUTEX_LOCK(cbs->list_mutex);
264        cbs->list = my_g_slist_filter (cbs->list, callback_equal_predicate, callback);
265        MUTEX_UNLOCK(cbs->list_mutex);
266}
267
268void
269gnome_vfs_message_callbacks_remove_by_data (GnomeVFSMessageCallbacks *cbs,
270                                            gpointer                  user_data)
271{
272        MUTEX_LOCK(cbs->list_mutex);
273        cbs->list = my_g_slist_filter (cbs->list, data_equal_predicate, user_data);
274        MUTEX_UNLOCK(cbs->list_mutex);
275}
276
277void
278gnome_vfs_message_callbacks_remove_by_func_and_data (GnomeVFSMessageCallbacks *cbs,
279                                                     GnomeVFSStatusCallback    callback,
280                                    gpointer                  user_data)
281{
282        struct func_and_data fd;
283
284        MUTEX_LOCK(cbs->list_mutex);
285       
286        fd.func = callback;
287        fd.data = user_data;
288       
289        cbs->list = my_g_slist_filter (cbs->list, all_equal_predicate, &fd);
290
291        MUTEX_UNLOCK(cbs->list_mutex);
292}
293
294void
295gnome_vfs_message_callbacks_emit (GnomeVFSMessageCallbacks *cbs,
296                                  const gchar              *message)
297{
298        GSList *iter;
299
300        MUTEX_LOCK(cbs->list_mutex);
301       
302        iter = cbs->list;
303
304        while (iter != NULL) {
305                Callback *cb;
306
307                cb = iter->data;
308
309                callback_invoke (cb, message);
310               
311                iter = g_slist_next (iter);
312        }
313
314        MUTEX_UNLOCK(cbs->list_mutex);
315}
316
317
Note: See TracBrowser for help on using the repository browser.