GLib Event Loop

GLibEvent Loop

The GLib event loop manages all the sources of an event availablefor GLib. These events can come from different kinds of sources like filedescriptors (plain file descriptors, sockets, or pipes), time-outs, or anykind of source that can be added.

To allow multiple independent sets of events to be handled in differentthreads, each source is associated with a GMainContext.

Each event source is given a priority. The default priority is G_PRIORITY_DEFAULT andits value is 0. Values less than 0 denote higher priority and values greaterthan zero denote lower priority. The events from higher priority sources areprocessed earlier than events from lower priority sources.

The GMainLoop data type represents an event loop. GMainContext isa parameter to GMainLoop. If GMainContext ispassed as NULL, then a main loop with the default context is created. Afterthe sources are added to GMainContext and a GMainLoop variableis created, g_main_loop_run() is called. This checks continuouslyfor events from its sources and dispatches them. Finally when all the eventshave been processed, g_main_loop_quit() must be called toreturn from g_main_loop_run().

Note: Sources are associated with

GMainContext and not with GMainLoop.Events from sources will be checked and dispatched from all the GMainLoop the GMainContext isassociated with.

Creatingan event loop

GLib provides ready-made functions for addingthe following sources either to the default context or to a custom context:

  • time-outs

  • I/O

  • child watch

  • idle source (events from idle sources are ready if none of the othersources with priority > G_PRIORITY_DEFAULT are ready)

The following example code demonstrates the way to add a time-outsource to the default context. The program makes 10 calls to timeout_callback(),which at the 10th call, calls g_main_loop_quit to make themain loop return.

#include <glib.h>
gboolean timeout_callback(gpointer data)
{
    static int i = 0;
    
    i++;
    g_print("timeout_callback called %d times\n", i);
    if (10 == i)
    {
        g_main_loop_quit( (GMainLoop*)data );
        return FALSE;
    }

    return TRUE;
}

int main()
{
    GMainLoop *loop;

    loop = g_main_loop_new ( NULL , FALSE );

    // add source to default context
    g_timeout_add (100 , timeout_callback , loop); 
    g_main_loop_run (loop);
    g_main_loop_unref(loop);

    return 0;
}

The following code demonstrates the method to add the time-outsource to a different context than the default context:

#include <glib.h>
gboolean timeout_callback(gpointer data)
{
    static int i = 0;
    
    i++;
    g_print("timeout_callback called %d times\n",i);
    
    if(10 == i)
    {
        g_main_loop_quit((GMainLoop*)data);
        return FALSE;
    }
	
    return TRUE;
}

int main()
{
    GMainLoop *loop = NULL;
    GMainContext *context;
    GSource *source;
    int id;
		
    //create a new time-out source
    source = g_timeout_source_new(10);

    //create a context
    context = g_main_context_new();

    //attach source to context
    id = g_source_attach(source,context);
 
    //create a main loop with context
    loop = g_main_loop_new(context,FALSE);
	
    //set the callback for this source
    g_source_set_callback (source,timeout_callback,loop,NULL);
	
    g_main_loop_run (loop);
    
    g_main_loop_unref (loop);
     
    return 0;
}

The same process can be used for other default sources likechild watch, I/O, and idle source since they are GLib APIs that allow thecreation of a source directly.

Creating anew source

The previous section applies only to four types of sources( time-outs, I/O, child watch, and idle source ), for which GLib providesready-made functions. The program below demonstrates the creation of a newsource.

#include <glib.h>
gboolean callback(gpointer data)
{
    static int i = 0;
    i++;
    g_print ("timeout_callback called %d times\n",i);
    if (10 == i)
    {
        g_main_loop_quit((GMainLoop*)data);
        return FALSE;
    }

    return TRUE;
}

gboolean prepare(GSource *source,gint *timeout_)
{
    *timeout_ = -1;
    return TRUE;
}

gboolean check(GSource *source)
{
    return TRUE;
}

gboolean dispatch(GSource *source,GSourceFunc callback,gpointer user_data)
{
    if (callback(user_data))
        return TRUE;
    else
        return FALSE;
}

int main()
{
    GMainLoop *loop = NULL;
    GMainContext *context;
    GSource *source;
    int id;
	
    //create a variable of type GSourceFuncs
    GSourceFuncs SourceFuncs =
    {
        prepare,
        check,
        dispatch,
        NULL
    };
	
    //create a new source
    source = g_source_new (&SourceFuncs, sizeof(GSource));
	
    //create a context
    context = g_main_context_new ();
	
    //attach source to context
    id = g_source_attach (source,context);
	
    //create a main loop with context
    loop = g_main_loop_new (context,FALSE);
 
    //set the callback for this source
    g_source_set_callback (source,callback,loop,NULL);
	
    g_main_loop_run (loop);
    g_main_loop_unref (loop);
	
    return 0;
}

The creation of a new source requires us to define at least3 functions:

  • prepare(): Called before all the file descriptorsare polled. If the source can determine that it is ready here (without waitingfor the results of the poll() call), it should return TRUE. It can also returna time-out value which should be the maximum time-out (in milliseconds) whichshould be passed to the poll() call. The actual time-out used will be -1 ifall sources returned -1, or it will be the minimum of all the timeout_valuesreturned which were >= 0

  • check(): Called after all the file descriptorsare polled. The source should return TRUE if it is ready to be dispatched.

    Note: Timemay have passed since the previous prepare function was called, so the sourceshould be checked again.

  • dispatch() Called to dispatch the event sourceafter it has returned TRUE in either its prepare or check function. The dispatchfunction is passed in a callback function and data. The callback functionmay be NULL if the source was never connected to a callback using g_source_set_callback().The dispatch function should call the callback function with user_data andthe additional parameters that are needed for this type of event source.

Customizingthe main loop iteration

Single iteration of GMainContext canbe run in g_main_context_iteration (). When a more detailedcontrol of how the main loop runs is desired call the component function of g_main_contextiteration() directly.

The component functions of g_main_contextiteration() are listed below:

  • g_main_context_prepare()

  • g_main_context_query()

  • g_main_context_check()

References:

https://developer.gnome.org/programming-guidelines/stable/main-contexts.html.en

http://devlib.symbian.slions.net/s3/GUID-7FD05006-09C1-4EF4-A2EB-AD98C2FA8866.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值