source: trunk/third/libsoup/libsoup/soup-message-queue.c @ 21108

Revision 21108, 5.3 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21107, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * soup-message-queue.c: Message queue
4 *
5 * Copyright (C) 2003, Ximian, Inc.
6 */
7
8#ifdef HAVE_CONFIG_H
9#include <config.h>
10#endif
11
12#include "soup-message-queue.h"
13
14struct SoupMessageQueue {
15        GList *head, *tail;
16        GList *iters;
17
18        GMutex *mutex;
19};
20
21/**
22 * soup_message_queue_new:
23 *
24 * Creates a new #SoupMessageQueue
25 *
26 * Return value: a new #SoupMessageQueue object
27 **/
28SoupMessageQueue *
29soup_message_queue_new (void)
30{
31        SoupMessageQueue *queue;
32
33        queue = g_new0 (SoupMessageQueue, 1);
34        queue->mutex = g_mutex_new ();
35        return queue;
36}
37
38/**
39 * soup_message_queue_destroy:
40 * @queue: a message queue
41 *
42 * Frees memory associated with @queue, which must be empty.
43 **/
44void
45soup_message_queue_destroy (SoupMessageQueue *queue)
46{
47        g_return_if_fail (queue->head == NULL);
48
49        g_list_free (queue->head);
50        g_list_free (queue->iters);
51        g_mutex_free (queue->mutex);
52        g_free (queue);
53}
54
55/**
56 * soup_message_queue_append:
57 * @queue: a queue
58 * @msg: a message
59 *
60 * Appends @msg to the end of @queue
61 **/
62void
63soup_message_queue_append (SoupMessageQueue *queue, SoupMessage *msg)
64{
65        g_mutex_lock (queue->mutex);
66        if (queue->head) {
67                queue->tail = g_list_append (queue->tail, msg);
68                queue->tail = queue->tail->next;
69        } else
70                queue->head = queue->tail = g_list_append (NULL, msg);
71
72        g_object_add_weak_pointer (G_OBJECT (msg), &queue->tail->data);
73        g_mutex_unlock (queue->mutex);
74}
75
76/**
77 * soup_message_queue_first:
78 * @queue: a queue
79 * @iter: pointer to a #SoupMessageQueueIter
80 *
81 * Initializes @iter and returns the first element of @queue. If you
82 * do not iterate all the way to the end of the list, you must call
83 * soup_message_queue_free_iter() to dispose the iterator when you are
84 * done.
85 *
86 * Return value: the first element of @queue, or %NULL if it is empty.
87 **/
88SoupMessage *
89soup_message_queue_first (SoupMessageQueue *queue, SoupMessageQueueIter *iter)
90{
91        g_mutex_lock (queue->mutex);
92
93        if (!queue->head) {
94                g_mutex_unlock (queue->mutex);
95                return NULL;
96        }
97
98        queue->iters = g_list_prepend (queue->iters, iter);
99
100        iter->cur = NULL;
101        iter->next = queue->head;
102        g_mutex_unlock (queue->mutex);
103
104        return soup_message_queue_next (queue, iter);
105}
106
107static SoupMessage *
108queue_remove_internal (SoupMessageQueue *queue, SoupMessageQueueIter *iter)
109{
110        GList *i;
111        SoupMessageQueueIter *iter2;
112        SoupMessage *msg;
113
114        if (!iter->cur) {
115                /* We're at end of list or this item was already removed */
116                return NULL;
117        }
118
119        /* Fix any other iters pointing to iter->cur */
120        for (i = queue->iters; i; i = i->next) {
121                iter2 = i->data;
122                if (iter2 != iter) {
123                        if (iter2->cur == iter->cur)
124                                iter2->cur = NULL;
125                        else if (iter2->next == iter->cur)
126                                iter2->next = iter->cur->next;
127                }
128        }
129
130        msg = iter->cur->data;
131        if (msg)
132                g_object_remove_weak_pointer (G_OBJECT (msg), &iter->cur->data);
133
134        /* If deleting the last item, fix tail */
135        if (queue->tail == iter->cur)
136                queue->tail = queue->tail->prev;
137
138        /* Remove the item */
139        queue->head = g_list_delete_link (queue->head, iter->cur);
140        iter->cur = NULL;
141
142        return msg;
143}
144
145/**
146 * soup_message_queue_next:
147 * @queue: a queue
148 * @iter: pointer to an initialized #SoupMessageQueueIter
149 *
150 * Returns the next element of @queue
151 *
152 * Return value: the next element, or %NULL if there are no more.
153 **/
154SoupMessage *
155soup_message_queue_next (SoupMessageQueue *queue, SoupMessageQueueIter *iter)
156{
157        g_mutex_lock (queue->mutex);
158
159        while (iter->next) {
160                iter->cur = iter->next;
161                iter->next = iter->cur->next;
162                if (iter->cur->data) {
163                        g_mutex_unlock (queue->mutex);
164                        return iter->cur->data;
165                }
166
167                /* Message was finalized, remove dead queue element */
168                queue_remove_internal (queue, iter);
169        }
170
171        /* Nothing left */
172        iter->cur = NULL;
173        queue->iters = g_list_remove (queue->iters, iter);
174
175        g_mutex_unlock (queue->mutex);
176        return NULL;
177}
178
179/**
180 * soup_message_queue_remove:
181 * @queue: a queue
182 * @iter: pointer to an initialized #SoupMessageQueueIter
183 *
184 * Removes the queue element pointed to by @iter; that is, the last
185 * message returned by soup_message_queue_first() or
186 * soup_message_queue_next().
187 *
188 * Return value: the removed message, or %NULL if the element pointed
189 * to by @iter was already removed.
190 **/
191SoupMessage *
192soup_message_queue_remove (SoupMessageQueue *queue, SoupMessageQueueIter *iter)
193{
194        SoupMessage *msg;
195
196        g_mutex_lock (queue->mutex);
197        msg = queue_remove_internal (queue, iter);
198        g_mutex_unlock (queue->mutex);
199
200        return msg;
201}
202
203/**
204 * soup_message_queue_remove_message:
205 * @queue: a queue
206 * @msg: a #SoupMessage
207 *
208 * Removes the indicated message from @queue.
209 **/
210void
211soup_message_queue_remove_message (SoupMessageQueue *queue, SoupMessage *msg)
212{
213        SoupMessageQueueIter iter;
214        SoupMessage *msg2;
215
216        for (msg2 = soup_message_queue_first (queue, &iter); msg2; msg2 = soup_message_queue_next (queue, &iter)) {
217                if (msg2 == msg) {
218                        soup_message_queue_remove (queue, &iter);
219                        soup_message_queue_free_iter (queue, &iter);
220                        return;
221                }
222        }
223}
224
225
226/**
227 * soup_message_queue_free_iter:
228 * @queue: a queue
229 * @iter: pointer to an initialized #SoupMessageQueueIter
230 *
231 * Removes @iter from the list of active iterators in @queue.
232 **/
233void
234soup_message_queue_free_iter (SoupMessageQueue *queue,
235                              SoupMessageQueueIter *iter)
236{
237        g_mutex_lock (queue->mutex);
238        queue->iters = g_list_remove (queue->iters, iter);
239        g_mutex_unlock (queue->mutex);
240}
Note: See TracBrowser for help on using the repository browser.