Outils pour utilisateurs

Outils du site


allegro:threads

====== Différences ====== Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

allegro:threads [2012/03/16 23:54]
mrhide [Exemple basique]
allegro:threads [2012/06/29 17:02] (Version actuelle)
mrhide [Threads]
Ligne 1: Ligne 1:
-===== Threads =====+===== Allegro — Threads =====
  
 Dans cet article nous allons voir comment utiliser l'​interface de threading d'​Allegro. Dans cet article nous allons voir comment utiliser l'​interface de threading d'​Allegro.
- 
-FIXME faire le walktrough 
  
 ==== Exemple basique ==== ==== Exemple basique ====
Ligne 18: Ligne 16:
 { {
    ​ALLEGRO_MUTEX ​  ​*mutex;​    ​ALLEGRO_MUTEX ​  ​*mutex;​
-   ​ALLEGRO_COND ​   *cond; 
    ​ALLEGRO_DISPLAY *display;    ​ALLEGRO_DISPLAY *display;
    ​ALLEGRO_BITMAP ​ *caret;    ​ALLEGRO_BITMAP ​ *caret;
Ligne 26: Ligne 23:
 { {
    ​data->​mutex ​  = al_create_mutex();​    ​data->​mutex ​  = al_create_mutex();​
-   ​data->​cond ​   = al_create_cond();​ 
    ​data->​display = display;    ​data->​display = display;
    ​data->​caret ​  = caret;    ​data->​caret ​  = caret;
Ligne 34: Ligne 30:
 { {
    ​al_destroy_mutex(data->​mutex);​    ​al_destroy_mutex(data->​mutex);​
-   ​al_destroy_cond(data->​cond);​ 
 } }
  
Ligne 109: Ligne 104:
 } }
  
-static void *progressBar(ALLEGRO_THREAD *thr, void *arg) { +static void *progressBar(ALLEGRO_THREAD *thr, void *arg) 
 +{
    ​ALLEGRO_TIMER ​      ​*timer ​      = NULL;    ​ALLEGRO_TIMER ​      ​*timer ​      = NULL;
    ​ALLEGRO_EVENT_QUEUE *event_queue = NULL;    ​ALLEGRO_EVENT_QUEUE *event_queue = NULL;
Ligne 161: Ligne 156:
 ==== Détails ==== ==== Détails ====
  
 +<code c>
 +typedef struct s_data ​
 +{
 +   ​ALLEGRO_MUTEX ​  ​*mutex;​
 +   ​ALLEGRO_DISPLAY *display;
 +   ​ALLEGRO_BITMAP ​ *caret;
 +} DATA;
 +
 +void init_DATA(DATA *data, ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP ​ *caret)
 +{
 +   ​data->​mutex ​  = al_create_mutex();​
 +   ​data->​display = display;
 +   ​data->​caret ​  = caret;
 +}
 +
 +void dest_DATA(DATA *data)
 +{
 +   ​al_destroy_mutex(data->​mutex);​
 +}
 +</​code>​
 +
 +On crée une structure qui contient les ressources partagées, elle doit contenir minimum le **mutex** qui permet de demander l'​accès exclusif aux données afin d'​éviter de les corrompre (si par exemple 2 threads veulent modifier la même variable au même moment, la valeur finale de la variable est inconnue).
 +
 +//On peut ajouter une **condition** de type **ALLEGRO_COND** qui permet à un thread d'en interrompre un autre et le de relancer grâce aux fonctions **al_wait_cond** et **al_broadcast_cond**,​ utile pour les threads concurrents.//​
 +
 +<code c>
 +   ​thread = al_create_thread(progressBar,​ &data);
 +   ​al_start_thread(thread);​
 +    ​
 +   ​al_rest(10.0);​ /* Loading some awesome datas !! */
 +</​code>​
 +
 +On crée notre thread avec **al_create_thread** qui prend en paramètres une fonction (qui sera appelée par le thread nouvellement crée) et un argument (qui sera transmis à la fonction).
 +
 +**al_start_thread** démarre notre thread, ensuite on peut faire tourner le code gros consommateur de temps (représenté par **al_rest**),​ on sait que l'​affichage est géré par la fonction **progressBar**.
 +
 +C'est une fonction très simple que reprend des notions des articles précédents. Sachez que dessiner la barre de progression avec un bitmap c'est pas très intelligent ! on dispose de fonctions de dessin via ce greffon : [[allegro:​addon_primitives|Primitive]].
 +
 +On remarquera seulement ceci :
 +
 +<code c>
 +   ​al_set_target_bitmap(al_get_backbuffer(data->​display));​ /* new context */
 +</​code>​
 +
 +En effet, chaque thread possède son propre context, c'est à dire tout ce qui est global dans allegro est limité à un thread, donc pour pouvoir dessiner sur le canvas démarré dans le thread principal, il faut le transmettre via notre structure et prévenir notre nouveau thread.\\
 +Si votre jeu termine sur un **ASSERT**, c'est certainement du à une variable du context qui est à **NULL**, donc faites attention !
 +
 +==== Amelioration ====
 +
 +On décide d'​améliorer notre barre de progression,​ on veut que le thread principal contrôle l'​avancement de la barre : on ajoute donc la variable **data.percent**,​ un entier compris entre 0 et 100 pour définir la taille de notre barre en fonction de l'​avancement dans notre thread principal.\\
 +On doit aussi ajouter une condition pour que le thread principal déclenche le dessin dès qu'il modifie la variable.
 +
 +On modifie alors notre fonction qui dépend plus du timer :
 +
 +<code c>
 +static void *progressBar(ALLEGRO_THREAD *thr, void *arg)
 +{
 +   DATA *data  = (DATA*) arg;
 +   float pbar_1pc = (SCREEN_W-2*PADDING)/​100.0;​
 +   int goon = 1;
 +
 +   ​al_set_target_bitmap(al_get_backbuffer(data->​display));​
 +
 +   ​while(!al_get_thread_should_stop(thr) && goon)
 +   {
 +      al_lock_mutex(data->​mutex);​
 +      al_wait_cond(data->​cond,​ data->​mutex);​
 +      al_draw_bitmap(data->​caret,​ data->​percent*pbar_1pc,​ SCREEN_H-PADDING-CARET_HEIGHT,​ 0);
 +      if (data->​percent == 100)
 +         goon = 0;
 +      al_unlock_mutex(data->​mutex);​
 +
 +      al_flip_display();​
 +   }
 +
 +   ​return NULL;
 +}
 +</​code>​
 +
 +La fonction restera bloquée sur **al_wait_cond** tant que le thread parent n'a pas appelé **al_broadcast_cond**.
 +
 +Pour terminer ce type de thread, un **join** ne suffit pas car il n'​enlève pas les **locks** dûs aux conditions. Vous devez utiliser à la place :
 +
 +<code C>
 +    al_set_thread_should_stop(thread);​
 +    al_lock_mutex(data.mutex);​
 +    al_broadcast_cond(data.cond);​
 +    al_unlock_mutex(data.mutex);​
 +</​code>​
  
 +Maintenant que vous savez utiliser les threads, vous savez pratiquement tout ce qu'il y a à savoir sur le core d'​allegro,​ dans la suite de ce tutoriel nous aborderons les différents greffons d'​Allegro.
  
-[[allegro:​input|Précédent]] << [[allegro:​start|Sommaire]] >> [[allegro:​addons|Suivant]]+[[allegro:​input|Précédent]] << [[allegro:​start#articles|Sommaire]] >> [[allegro:​addons|Suivant]]
allegro/threads.1331938463.txt.gz · Dernière modification: 2012/03/16 23:54 par mrhide