Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

gtask-event-dispatcher.c

Go to the documentation of this file.
00001 #include <gtask/gtask-event-dispatcher.h>
00002 #include <gtask/gtask-packet.h>
00003 
00004 #include <gtask/gtask-internals.h>
00005 
00006 typedef struct _WatchInfo {
00007     guint          watch_id;
00008     GType          watch_type;
00009     GTaskEventFunc func;
00010     gpointer       data;
00011 } WatchInfo;
00012 
00013 static gpointer parent_class;
00014 
00015 static void
00016 gtask_event_dispatcher_class_init( GTaskEventDispatcherClass *klass );
00017 
00018 static void
00019 gtask_event_dispatcher_init( GTaskEventDispatcher *dispatcher, gpointer g_class );
00020 
00021 static void
00022 gtask_event_dispatcher_dispose( GObject *obj );
00023 
00024 static void
00025 gtask_event_dispatcher_finalize( GObject *obj );
00026 
00027 GType gtask_event_dispatcher_get_type( void ) {
00028     static GType type = 0;
00029 
00030     if( type == 0 ) {
00031         static const GTypeInfo info = {
00032             sizeof( GTaskEventDispatcherClass ),
00033             NULL,   /* base init */
00034             NULL,   /* base_finalize */
00035             (GClassInitFunc) gtask_event_dispatcher_class_init, /* class_init */
00036             NULL,   /* class_finalize */
00037             NULL,   /* class_data */
00038             sizeof( GTaskEventDispatcher ),
00039             0,      /* n_preallocs */
00040             (GInstanceInitFunc) gtask_event_dispatcher_init
00041         };
00042 
00043         type = g_type_register_static( G_TYPE_OBJECT,
00044                                        "GTaskEventDispatcher",
00045                                        &info,
00046                                        0 );
00047     }
00048 
00049     return type;
00050 }
00051 
00052 static void
00053 gtask_event_dispatcher_class_init( GTaskEventDispatcherClass *klass ) {
00054     GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
00055 
00056     parent_class = g_type_class_peek_parent( klass );
00057 
00058     gobject_class->dispose = gtask_event_dispatcher_dispose;
00059     gobject_class->finalize = gtask_event_dispatcher_finalize;
00060 }
00061 
00062 static void
00063 gtask_event_dispatcher_init( GTaskEventDispatcher *dispatcher,
00064                              gpointer g_class )
00065 {
00066     GTaskEventDispatcherPrivate *private = g_new0( GTaskEventDispatcherPrivate, 1 );
00067 
00068     private->dispose_has_run = FALSE;
00069     private->watches = g_array_new( FALSE, TRUE, sizeof( WatchInfo ) );
00070     private->next_watch_id = 1;
00071 
00072     dispatcher->private = private;
00073 }
00074 
00075 static void
00076 gtask_event_dispatcher_dispose( GObject *obj ) {
00077     GTaskEventDispatcher        *dispatcher = GTASK_EVENT_DISPATCHER( obj );
00078     GTaskEventDispatcherPrivate *private = dispatcher->private;
00079 
00080     if( private->dispose_has_run )
00081         return;
00082 
00083     g_object_unref( private->parser );
00084 
00085     private->dispose_has_run = TRUE;
00086 
00087     if( G_OBJECT_CLASS( parent_class )->dispose )
00088         G_OBJECT_CLASS( parent_class )->dispose( obj );
00089 }
00090 
00091 static void
00092 gtask_event_dispatcher_finalize( GObject *obj ) {
00093     GTaskEventDispatcher        *dispatcher = GTASK_EVENT_DISPATCHER( obj );
00094     GTaskEventDispatcherPrivate *private = dispatcher->private;
00095 
00096     g_array_free( private->watches, TRUE );
00097     g_free( private );
00098 
00099     if( G_OBJECT_CLASS( parent_class )->finalize )
00100         G_OBJECT_CLASS( parent_class )->finalize( obj );
00101 }
00102 
00120 GTaskEventDispatcher *
00121 gtask_event_dispatcher_new_with_parser( GTaskStreamParser *parser ) {
00122     GTaskEventDispatcher *dispatcher;
00123 
00124     g_return_val_if_fail( GTASK_IS_STREAM_PARSER( parser ), NULL );
00125 
00126     dispatcher = g_object_new( GTASK_EVENT_DISPATCHER_TYPE, NULL );
00127 
00128     g_object_ref( parser );
00129 
00130     dispatcher->private->parser = parser;
00131 
00132     return dispatcher;
00133 }
00134 
00152 guint
00153 gtask_event_dispatcher_add_watch( GTaskEventDispatcher *dispatch,
00154                                   GType watch_type,
00155                                   GTaskEventFunc func,
00156                                   gpointer user_data )
00157 {
00158     WatchInfo info;
00159 
00160     g_return_val_if_fail( GTASK_IS_EVENT_DISPATCHER( dispatch ), 0 );
00161 
00162     g_debug( "IN: gtask_event_dispatcher_add_watch" );
00163 
00164     info.watch_id = dispatch->private->next_watch_id++;
00165     info.watch_type = watch_type;
00166     info.func = func;
00167     info.data = user_data;
00168 
00169     g_array_append_val( dispatch->private->watches, info );
00170 
00171     g_debug( "LEAVING: gtask_event_dispatcher_add_watch" );
00172     return info.watch_id;
00173 }
00174 
00181 void
00182 gtask_event_dispatcher_remove_watch( GTaskEventDispatcher *dispatch,
00183                                      guint watch_id )
00184 {
00185     GTaskEventDispatcherPrivate *private;
00186     guint                        i;
00187 
00188     g_return_if_fail( GTASK_IS_EVENT_DISPATCHER( dispatch ) );
00189     g_return_if_fail( watch_id > 0 );
00190 
00191     g_debug( "IN: gtask_event_dispatcher_remove_watch" );
00192 
00193     private = dispatch->private;
00194 
00195     for( i = 0; i < private->watches->len; i++ ) {
00196         WatchInfo info = g_array_index( private->watches, WatchInfo, i );
00197 
00198         if( info.watch_id == watch_id )
00199             g_array_remove_index( private->watches, i-- );
00200         else if( info.watch_id > watch_id )
00201             return;
00202     }
00203 
00204     g_debug( "LEAVING: gtask_event_dispatcher_remove_watch" );
00205 }
00206 
00217 GTaskStreamParser *
00218 gtask_event_dispatcher_get_stream_parser( GTaskEventDispatcher *dispatch ) {
00219     g_return_val_if_fail( GTASK_IS_EVENT_DISPATCHER( dispatch ), NULL );
00220 
00221     return dispatch->private->parser;
00222 }
00223 
00224 
00236 gboolean
00237 gtask_event_dispatcher_private_parse_callback( GIOChannel *chann,
00238                                                GIOCondition cond,
00239                                                gpointer data )
00240 {
00241     GTaskEventDispatcher *dispatcher;
00242     GTaskStreamParser    *parser;
00243     GIOStatus             status;
00244     GObject              *packet;
00245     GArray               *remove;
00246     gchar                 buff[1025];
00247     guint                 num;
00248     guint                 i;
00249 
00250     g_debug( "IN: gtask_event_dispatcher_private_parse_callback()" );
00251 
00252     g_return_val_if_fail( cond == G_IO_IN, TRUE );
00253     g_return_val_if_fail( GTASK_IS_EVENT_DISPATCHER( data ), FALSE );
00254 
00255     dispatcher = GTASK_EVENT_DISPATCHER( data );
00256     remove = g_array_new( FALSE, FALSE, sizeof( guint ) );
00257 
00258     parser = gtask_event_dispatcher_get_stream_parser( dispatcher );
00259 
00260     status = g_io_channel_read_chars( chann, buff, 1024, &num, NULL );
00261 
00262     buff[num] = '\0';
00263 
00264     switch( status ) {
00265         case G_IO_STATUS_EOF:
00267             return FALSE;
00268         case G_IO_STATUS_ERROR:
00269             g_message( "status == G_IO_STATUS_ERROR" );
00271             return FALSE;
00272         case G_IO_STATUS_AGAIN:
00273             return TRUE;
00274         default:
00275             break;
00276     }
00277 
00278     if( !gtask_stream_parser_push_data( parser, buff, num ) ) {
00279         g_warning( "parsing error on stream" );
00280         return FALSE;
00281     }
00282 
00283     if( !gtask_stream_parser_has_packets( parser ) ) {
00284         g_warning( "no new packets created" );
00285         return TRUE;
00286     }
00287 
00288     g_debug( "new packets are in the queue" );
00289     while( ( packet = gtask_stream_parser_get_next_packet( parser ) ) != NULL )
00290     {
00291         GType   type = G_OBJECT_TYPE( packet );
00292         GArray *watches = dispatcher->private->watches;
00293         guint   len = watches->len;
00294 
00295         g_debug( "EventDispatcher: packet_type: %s", G_OBJECT_TYPE_NAME( packet ) );
00296 
00297         for( i = 0; i < len; i++ ) {
00298             WatchInfo info = g_array_index( watches, WatchInfo, i );
00299 
00300             if( g_type_is_a( type, info.watch_type ) ) {
00301                 g_warning( "dispatching to watch candidate: %p", packet );
00302 
00303                 if( !info.func( dispatcher, (GObject *) packet, info.data ) ) {
00304                     g_array_append_val( remove, i );
00305                 }
00306 
00307                 g_warning( "done dispatching to watch candidate: %p", packet );
00308             }
00309         }
00310 
00311         g_warning( "unref'ing packet: %p %s", packet, G_OBJECT_TYPE_NAME( packet ) );
00312         if( !G_IS_OBJECT( packet ) ) {
00313             g_warning( "WTF?! it's not an object?" );
00314         } else {
00315             g_warning( "Back in the real world glib thinks this is an object" );
00316         }
00317         g_object_unref( packet );
00318         g_warning( "done unref'ing packet" );
00319     }
00320     g_warning( "no more packets" );
00321 
00322     for( i = 0; i < remove->len; i++ ) {
00323         gtask_event_dispatcher_remove_watch( dispatcher,
00324                                             g_array_index( remove, guint, i ) );
00325     }
00326 
00327     g_warning( "done removing people" );
00328 
00329     g_array_free( remove, TRUE );
00330 
00331     g_debug( "LEAVING: gtask_event_dispatcher_private_parse_callback()" );
00332 
00333     return TRUE;
00334 }

Generated on Mon Feb 2 21:26:14 2004 for libgtask by doxygen 1.3.4