loudmouth/src/lm-message-queue.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
equal deleted inserted replaced
0:d0f3a028347a 10:59927b2d3b75
     1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
       
     2 /*
       
     3  * Copyright (C) 2006 Imendio AB
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Lesser General Public License as
       
     7  * published by the Free Software Foundation; either version 2 of the
       
     8  * License, or (at your option) any later version.
       
     9  *
       
    10  * This program is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Lesser General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Lesser General Public
       
    16  * License along with this program; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 #include <config.h>
       
    22 
       
    23 #include "lm-message-queue.h"
       
    24 #include "lm-debug.h"
       
    25 
       
    26 struct _LmMessageQueue {
       
    27 	GQueue                  *messages;
       
    28 
       
    29 	GMainContext            *context;
       
    30 	GSource                 *source;
       
    31 
       
    32 	LmMessageQueueCallback  callback;
       
    33 	gpointer                user_data;
       
    34 
       
    35 	gint                    ref_count;
       
    36 };
       
    37 
       
    38 typedef struct {
       
    39 	GSource         source;
       
    40 	LmMessageQueue *queue;
       
    41 } MessageQueueSource;
       
    42 
       
    43 static void        message_queue_free            (LmMessageQueue *queue);
       
    44 static gboolean    message_queue_prepare_func    (GSource         *source,
       
    45 						  gint            *timeout);
       
    46 static gboolean    message_queue_check_func      (GSource         *source);
       
    47 static gboolean    message_queue_dispatch_func   (GSource         *source,
       
    48 						  GSourceFunc      callback,
       
    49 						  gpointer         user_data);
       
    50 
       
    51 static GSourceFuncs source_funcs = {
       
    52 	message_queue_prepare_func,
       
    53 	message_queue_check_func,
       
    54 	message_queue_dispatch_func,
       
    55 	NULL
       
    56 };
       
    57 
       
    58 static void
       
    59 foreach_free_message (LmMessage *m, gpointer user_data)
       
    60 {
       
    61 	lm_message_unref (m);
       
    62 	UNUSED_FORMAL_PARAM(user_data);
       
    63 }
       
    64 
       
    65 static void
       
    66 message_queue_free (LmMessageQueue *queue)
       
    67 {
       
    68 	lm_message_queue_detach (queue);
       
    69 	
       
    70 	g_queue_foreach (queue->messages, (GFunc) foreach_free_message, NULL);
       
    71 	g_queue_free (queue->messages);
       
    72 
       
    73 	g_free (queue);
       
    74 }
       
    75 
       
    76 //Prepare has to return true for check method to be called.
       
    77 static gboolean
       
    78 message_queue_prepare_func (GSource *source, gint *timeout)
       
    79 {
       
    80 	LmMessageQueue *queue;
       
    81 
       
    82 	queue = ((MessageQueueSource *)source)->queue;
       
    83 	UNUSED_FORMAL_PARAM(timeout);
       
    84 	return !g_queue_is_empty (queue->messages);
       
    85 }
       
    86 
       
    87 //check has to return true for Dispatch method to be called.
       
    88 static gboolean
       
    89 message_queue_check_func (GSource *source)
       
    90 {
       
    91 //	return FALSE;
       
    92 UNUSED_FORMAL_PARAM(source);
       
    93 return TRUE;
       
    94 }
       
    95 
       
    96 static gboolean
       
    97 message_queue_dispatch_func (GSource     *source,
       
    98 			     GSourceFunc  callback,
       
    99 			     gpointer     user_data)
       
   100 {
       
   101 	LmMessageQueue *queue;
       
   102 
       
   103 	queue = ((MessageQueueSource *)source)->queue;
       
   104 
       
   105 	if (queue->callback) {
       
   106 		(queue->callback) (queue, queue->user_data);
       
   107 	}
       
   108 	UNUSED_FORMAL_PARAM(source);
       
   109 	UNUSED_FORMAL_PARAM(callback);
       
   110 	return TRUE;
       
   111 }
       
   112 
       
   113 LmMessageQueue *
       
   114 lm_message_queue_new (LmMessageQueueCallback  callback,
       
   115 		      gpointer                user_data)
       
   116 {
       
   117 	LmMessageQueue *queue;
       
   118 
       
   119 	queue = g_new0 (LmMessageQueue, 1);
       
   120 
       
   121 	queue->messages = g_queue_new ();
       
   122 	queue->context = NULL;
       
   123 	queue->source = NULL;
       
   124 	queue->ref_count = 1;
       
   125 
       
   126 	queue->callback = callback;
       
   127 	queue->user_data = user_data;
       
   128 
       
   129 	return queue;
       
   130 }
       
   131 
       
   132 void
       
   133 lm_message_queue_attach (LmMessageQueue *queue, GMainContext *context)
       
   134 {
       
   135 	GSource *source;
       
   136 
       
   137 	if (queue->source) {
       
   138 		if (queue->context == context) {
       
   139 			/* Already attached */
       
   140 			return;
       
   141 		}
       
   142 		lm_message_queue_detach (queue);
       
   143 	}
       
   144 
       
   145 	if (context)  {
       
   146 		queue->context = g_main_context_ref (context);
       
   147 	}
       
   148 	
       
   149 	source = g_source_new (&source_funcs, sizeof (MessageQueueSource));
       
   150 	((MessageQueueSource *)source)->queue = queue;
       
   151 	queue->source = source;
       
   152 
       
   153 	g_source_attach (source, queue->context);
       
   154 }
       
   155 
       
   156 void
       
   157 lm_message_queue_detach (LmMessageQueue *queue)
       
   158 {
       
   159 	if (queue->source) {
       
   160 		g_source_destroy (queue->source);
       
   161 		g_source_unref (queue->source);
       
   162 	}
       
   163 
       
   164 	if (queue->context) {
       
   165 		g_main_context_unref (queue->context);
       
   166 	}
       
   167 
       
   168 	queue->source = NULL;
       
   169 	queue->context = NULL;
       
   170 }
       
   171 
       
   172 void
       
   173 lm_message_queue_push_tail (LmMessageQueue *queue, LmMessage *m)
       
   174 {
       
   175 	g_return_if_fail (queue != NULL);
       
   176 	g_return_if_fail (m != NULL);
       
   177 
       
   178 	g_queue_push_tail (queue->messages, m);
       
   179 }
       
   180 
       
   181 LmMessage *
       
   182 lm_message_queue_peek_nth (LmMessageQueue *queue, guint n)
       
   183 {
       
   184 	g_return_val_if_fail (queue != NULL, NULL);
       
   185 
       
   186 	return (LmMessage *) g_queue_peek_nth (queue->messages, n);
       
   187 }
       
   188 
       
   189 LmMessage *
       
   190 lm_message_queue_pop_nth (LmMessageQueue *queue, guint n)
       
   191 {
       
   192 	g_return_val_if_fail (queue != NULL, NULL);
       
   193 
       
   194 	return (LmMessage *) g_queue_pop_nth (queue->messages, n);
       
   195 }
       
   196 
       
   197 guint
       
   198 lm_message_queue_get_length (LmMessageQueue *queue)
       
   199 {
       
   200 	g_return_val_if_fail (queue != NULL, 0);
       
   201 
       
   202 	return g_queue_get_length (queue->messages);
       
   203 }
       
   204 
       
   205 gboolean 
       
   206 lm_message_queue_is_empty (LmMessageQueue *queue)
       
   207 {
       
   208 	g_return_val_if_fail (queue != NULL, TRUE);
       
   209 
       
   210 	return g_queue_is_empty (queue->messages);
       
   211 }
       
   212 
       
   213 LmMessageQueue *
       
   214 lm_message_queue_ref (LmMessageQueue *queue)
       
   215 {
       
   216 	g_return_val_if_fail (queue != NULL, NULL);
       
   217 
       
   218 	queue->ref_count++;
       
   219 
       
   220 	return queue;
       
   221 }
       
   222 
       
   223 void
       
   224 lm_message_queue_unref (LmMessageQueue *queue)
       
   225 {
       
   226 	g_return_if_fail (queue != NULL);
       
   227 
       
   228 	queue->ref_count--;
       
   229 
       
   230 	if (queue->ref_count <= 0) {
       
   231 		message_queue_free (queue);
       
   232 	}
       
   233 }
       
   234