No issues found
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2007 Jonathan Matthew
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * The Rhythmbox authors hereby grant permission for non-GPL compatible
11 * GStreamer plugins to be used and distributed together with GStreamer
12 * and Rhythmbox. This permission is above and beyond the permissions granted
13 * by the GPL license by which Rhythmbox is covered. If you modify this code
14 * you may extend this exception to your version of the code, but you are not
15 * obligated to do so. If you do not wish to do so, delete this exception
16 * statement from your version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 *
27 */
28
29 #include "config.h"
30
31 #include <rb-async-queue-watch.h>
32
33 /**
34 * SECTION:rb-async-queue-watch
35 * @short_description: GSource for watching a GAsyncQueue in the main loop
36 *
37 * This provides a way to feed work items to the main loop using a #GAsyncQueue
38 * without polling it.
39 */
40
41 /**
42 * RBAsyncQueueWatchFunc:
43 * @item: the item found in the queue
44 * @data: user data specified when creating the watch
45 *
46 * Callback to call when an item is found in the queue.
47 */
48
49 typedef struct {
50 GSource source;
51 GAsyncQueue *queue;
52 } RBAsyncQueueWatch;
53
54 static gboolean
55 rb_async_queue_watch_prepare (GSource *source, gint *timeout)
56 {
57 RBAsyncQueueWatch *watch = (RBAsyncQueueWatch *)source;
58 *timeout = -1;
59 return (g_async_queue_length (watch->queue) > 0);
60 }
61
62 static gboolean
63 rb_async_queue_watch_check (GSource *source)
64 {
65 RBAsyncQueueWatch *watch = (RBAsyncQueueWatch *)source;
66 return (g_async_queue_length (watch->queue) > 0);
67 }
68
69 static gboolean
70 rb_async_queue_watch_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
71 {
72 RBAsyncQueueWatch *watch = (RBAsyncQueueWatch *)source;
73 RBAsyncQueueWatchFunc cb = (RBAsyncQueueWatchFunc)callback;
74 gpointer item;
75
76 item = g_async_queue_try_pop (watch->queue);
77 if (item == NULL) {
78 return TRUE;
79 }
80
81 if (cb == NULL) {
82 return FALSE;
83 }
84
85 cb (item, user_data);
86 return TRUE;
87 }
88
89 static void
90 rb_async_queue_watch_finalize (GSource *source)
91 {
92 RBAsyncQueueWatch *watch = (RBAsyncQueueWatch *)source;
93
94 if (watch->queue != NULL) {
95 g_async_queue_unref (watch->queue);
96 watch->queue = NULL;
97 }
98 }
99
100 static GSourceFuncs rb_async_queue_watch_funcs = {
101 rb_async_queue_watch_prepare,
102 rb_async_queue_watch_check,
103 rb_async_queue_watch_dispatch,
104 rb_async_queue_watch_finalize
105 };
106
107 /**
108 * rb_async_queue_watch_new:
109 * @queue: the #GAsyncQueue to watch
110 * @priority: priority value for the #GSource
111 * @callback: callback to invoke when the queue is non-empty
112 * @user_data: user data to pass to the callback
113 * @notify: function to call to clean up the user data for the callback
114 * @context: the #GMainContext to attach the source to
115 *
116 * Creates a new #GSource that triggers when the #GAsyncQueue is
117 * non-empty. This is used in rhythmbox to process queues within
118 * #RhythmDB in the main thread without polling.
119 *
120 * Return value: the ID of the new #GSource
121 */
122 guint rb_async_queue_watch_new (GAsyncQueue *queue,
123 gint priority,
124 RBAsyncQueueWatchFunc callback,
125 gpointer user_data,
126 GDestroyNotify notify,
127 GMainContext *context)
128 {
129 GSource *source;
130 RBAsyncQueueWatch *watch;
131 guint id;
132
133 source = (GSource *) g_source_new (&rb_async_queue_watch_funcs,
134 sizeof (RBAsyncQueueWatch));
135
136 watch = (RBAsyncQueueWatch *)source;
137 watch->queue = g_async_queue_ref (queue);
138
139 if (priority != G_PRIORITY_DEFAULT)
140 g_source_set_priority (source, priority);
141
142 g_source_set_callback (source, (GSourceFunc) callback, user_data, notify);
143
144 id = g_source_attach (source, context);
145 g_source_unref (source);
146 return id;
147 }