Symbian3/SDK/Source/GUID-7FD05006-09C1-4EF4-A2EB-AD98C2FA8866.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Tue, 20 Jul 2010 12:00:49 +0100
changeset 13 48780e181b38
parent 0 89d6a7a84779
permissions -rw-r--r--
Week 28 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 1897 and Bug 1522.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-7FD05006-09C1-4EF4-A2EB-AD98C2FA8866" xml:lang="en"><title>GLib
Event Loop</title><shortdesc>The GLib event loop manages all the sources of an event available
for GLib. These events can come from different kinds of sources like file
descriptors (plain file descriptors, sockets, or pipes), time-outs, or any
kind of source that can be added.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>To allow multiple independent sets of events to be handled in different
threads, each source is associated with a <codeph>GMainContext</codeph>.</p>
<p>Each event source is given a priority. The default priority is <codeph>G_PRIORITY_DEFAULT</codeph> and
its value is 0. Values less than 0 denote higher priority and values greater
than zero denote lower priority. The events from higher priority sources are
processed earlier than events from lower priority sources.</p>
<p>The <codeph>GMainLoop</codeph> data type represents an event loop. <codeph>GMainContext</codeph> is
a parameter to <codeph>GMainLoop</codeph>. If <codeph>GMainContext</codeph> is
passed as NULL, then a main loop with the default context is created. After
the sources are added to <codeph>GMainContext</codeph> and a <codeph>GMainLoop</codeph> variable
is created, <codeph>g_main_loop_run()</codeph> is called. This checks continuously
for events from its sources and dispatches them. Finally when all the events
have been processed, <codeph>g_main_loop_quit()</codeph> must be called to
return from <codeph>g_main_loop_run()</codeph>.</p>
<note>Sources are associated with <codeph>GMainContext</codeph> and not with <codeph>GMainLoop</codeph>.
Events from sources will be checked and dispatched from all the <codeph>GMainLoop</codeph> the <codeph>GMainContext</codeph> is
associated with.</note>
<section id="GUID-FE1BB596-6331-4AB8-BC5A-C8ADE24ACE7B">       <title>Creating
an event loop</title>       <p>GLib provides ready-made functions for adding
the following sources either to the default context or to a custom context:</p><ul>
<li><p>time-outs</p></li>
<li><p>I/O</p></li>
<li><p>child watch</p></li>
<li><p>idle source (events from idle sources are ready if none of the other
sources with priority &gt; G_PRIORITY_DEFAULT are ready) </p></li>
</ul><p>The following example code demonstrates the way to add a time-out
source to the default context. The program makes 10 calls to <codeph>timeout_callback()</codeph>,
which at the 10th call, calls <codeph>g_main_loop_quit</codeph> to make the
main loop return.</p><codeblock xml:space="preserve">#include &lt;glib.h&gt;
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;
}
</codeblock><p>The following code demonstrates the method to add the time-out
source to a different context than the default context:</p><codeblock xml:space="preserve">#include &lt;glib.h&gt;
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;
}
</codeblock><p>The same process can be used for other default sources like
child watch, I/O, and idle source since they are GLib APIs that allow the
creation of a source directly.</p>     </section>
<section id="GUID-76BB5D34-F4C9-4015-8A52-2CDAB37716A0"><title>Creating a
new source</title><p>The previous section applies only to four types of sources
( time-outs, I/O, child watch, and idle source ), for which GLib provides
ready-made functions. The program below demonstrates the creation of a new
source.</p><codeblock xml:space="preserve">#include &lt;glib.h&gt;
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 (&amp;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;
}
</codeblock><p>The creation of a new source requires us to define at least
3 functions:</p><ul>
<li><p><b><codeph>prepare()</codeph></b>: Called before all the file descriptors
are polled. If the source can determine that it is ready here (without waiting
for the results of the poll() call), it should return TRUE. It can also return
a time-out value which should be the maximum time-out (in milliseconds) which
should be passed to the poll() call. The actual time-out used will be -1 if
all sources returned -1, or it will be the minimum of all the timeout_values
returned which were &gt;= 0</p></li>
<li><p><b><codeph>check()</codeph></b>: Called after all the file descriptors
are polled. The source should return TRUE if it is ready to be dispatched.</p><note>Time
may have passed since the previous prepare function was called, so the source
should be checked again.</note></li>
<li><p><b><codeph>dispatch()</codeph></b> Called to dispatch the event source
after it has returned TRUE in either its prepare or check function. The dispatch
function is passed in a callback function and data. The callback function
may be NULL if the source was never connected to a callback using <codeph>g_source_set_callback()</codeph>.
The dispatch function should call the callback function with <codeph>user_data</codeph> and
the additional parameters that are needed for this type of event source.</p></li>
</ul></section>
<section id="GUID-675507D7-A769-48DA-8EE6-2AA271C0EC86"><title>Customizing
the main loop iteration</title><p>Single iteration of <codeph>GMainContext</codeph> can
be run in <codeph>g_main_context_iteration ()</codeph>. When a more detailed
control of how the main loop runs is desired call the component function of <codeph>g_main_context
iteration()</codeph> directly.</p><p>The component functions of <codeph>g_main_context
iteration()</codeph> are listed below:</p><ul>
<li><p><codeph>g_main_context_prepare()</codeph></p></li>
<li><p><codeph>g_main_context_query()</codeph></p></li>
<li><p><codeph>g_main_context_check()</codeph> </p></li>
</ul></section>
</conbody></concept>