GLib/GLib Core
Dans ce chapitre, nous parlerons de plusieurs éléments du core de la GLib.
GThread
modifierNous allons commencer par les gthreads.
L'utilisation des GThread nécessite de compiler avec la directive suivante (gcc): -lgthread-2.0
Il s'agit d'une abstraction proposée par la glib pour utiliser des threads.
Il nous faut, pour ce cours, inclure 2 headers.
#include <stdio.h>
#include <glib.h>
Initialisons une variable qui sera accédée par 4 threads.
int variableSensible = 42;
Voici le mutex qui protégera notre variable.
GMutex* lock = NULL;
Nous allons créer la fonction qui sera exécutée par chaque thread. Il s'agit d'une boucle demandant une valeur pour variableSensible et qui l'affiche. Cette boucle est parcouru 15 fois par thread.
gpointer affiche(gpointer data) {
int cpt = 0;
while(cpt < 15) {
cpt++;
Voici la zone critique dans laquelle on accède à une variable commune. g_mutex_lock est une fonction pour s'approprier un verrou (mutex). Si le verrou est pris, le thread est mis en blocage. Si le thread est en blocage, il sera débloqué dès que le verrou (mutex) sera libéré.
g_mutex_lock(lock);
printf("%s, saisissez un nombre: ", data );
scanf("%i",&variableSensible);
printf("%s, vous avez saisi %i\n",data, variableSensible);
g_mutex_unlock permet de libérer un verrou. Si vous ne libérez pas votre verrou à la fin de la zone critique de votre code, vous laisserez les autres threads endormis.
g_mutex_unlock(lock);
Cette instruction oblige le thread courant à passer son tour.
g_thread_yield();
}
return 0;
}
Définissons un main pour exécuter notre programme.
int main(int argc, char* argv[]) {
Afin de pouvoir utiliser des gthreads, il faut initialiser le système de threads de la GLib.
g_thread_init( NULL );
Il faut allouer un mutex avant de pouvoir s'en servir.
lock = g_mutex_new();
g_thread_create est une fonction permettant de lancer un gthread. Le premier argument est la fonction exécutée par le thread, le deuxième est une donnée de votre choix (pointeur), le troisième argument doit valoir TRUE si vous souhaitez attendre la fin du thread avec g_thread_join, sinon faux. Le dernier argument peut être setté pour gérer les erreurs de votre thread avec GError.
GThread* t1 = g_thread_create( affiche, "Thread 1", TRUE, NULL );
GThread* t2 = g_thread_create( affiche, "Thread 2", TRUE, NULL );
GThread* t3 = g_thread_create( affiche, "Thread 3", TRUE, NULL );
GThread* t4 = g_thread_create( affiche, "Thread 4", TRUE, NULL );
g_thread_join permet d'attendre la fin d'un thread. Si vous n'attendez pas la fin de vos threads, le programme se terminera, car le return du main sera atteint.
g_thread_join( t1 );
g_thread_join( t2 );
g_thread_join( t3 );
g_thread_join( t4 );
return 0;
}
Commentez les appels à g_mutex_lock et g_mutex_unlock dans affiche. Observez le résultat.