Mémo.txt 3.33 KB
Note : à la différence du fork, un thread ne créer pas de nouveau processus.

#include <pthread.h>

--- Compilation /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\
Avec gcc il faut utiliser -l pthread
    gcc <programme> -l pthread

--- Fonction hôte du thread
C'est la fonction qui va être executer dans le thread, la forme est toujours :
    void *start_routine(void * args){
        // ...
    }

--- Création du thread
fonction :
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
    thread : id du thread (généré par la fonction)
    attr : attribu, (très, très) souvent NULL
    start_routine : fonction a executer dans le thread
    arg : les argument à passer à start_routine

exemple :
    pthread tid; //thread id
    pthread_create(&tid, NULL, thread_fonction, NULL);

--- Rejoindre un thread
Suspend le thread qui appel la fonction et attend la terminaison du thread en argument.
Un tread joinable (c'est le cas par défault) va attendre un pthread_join avant de libérer sa mémoire. Utiliser pthread_detach pour éviter ça.

fonction :
    int pthread_join(pthread_t thread, void **status);
    thread : l'id du thread à attendre
    status : code de retour du thread attendu (généré par la fonction)

exemple :
    pthread_join(tid, NULL);

--- Détachement des threads
Le mode détaché permet de libérer la mémoire après la terminaison. Sinon, il aurait fallu utiliser pthread_join pour le même résultat.

fonction :
    int pthread_detach(pthread_t thread);
    thread : l'id du tread à détacher

exemple:
    pthread_detach(tid);

--- Terminaison des threads
Termine le thread qui appel la fonction. Si le thread était le dernier actif, le processus se termine.

fonction :
    void pthread_exit(void *status);
    status : code de terminaison

exemple :
    pthread_exit(NULL);

--- Les arguments des fonctions
Les arguments sont tous en void*.

Pour faire passer un int (exemple) :
    // -- coté création thread : int -> int* -> void*
    int arg = 5;
    // arg est int
    // &arg est int*
    // (void *) &arg est void*
    pthread_create([...], (void *) &arg);

    // coté thread : void* -> int* -> int
    void *arg;
    // arg est void*
    // (int *) arg est int*
    // *((int *) arg) ou *(int *) arg est int
    int n = *(int *) arg;

Pour une chaine de char (exemple) :
    // -- coté création thread : char* -> void*
    char str[50];
    // str est char*
    // (void *) str est void *
    pthread_create([...], (void *) &str);

    // coté thread : void* -> char*
    void *arg;
    // arg est void*
    // (char *) arg est char*
    char *str = (char *) arg;

Pour plusieur arguments, utiliser une structure (exemple) :
    struct deux_int {
        int a;
        int b;
    }

    // -- coté création thread : struct deux_int -> struct deux_int* -> void*
    int a = 1;
    int b = 3;
    struct deux_int ints;
    ints.a = a;
    ints.b = b;
    // ints est struct deux_int
    // &ints est struct deux_int*
    // (void *) &ints est void*
    pthread_create([...], (void *) &ints);

    // coté thread : void* -> struct deux_int* -> struct deux_int
    void *arg;
    // arg est void*
    // (struct deux_int *) arg est struct deux_int*
    // *(struct deux_int *) arg est struct deux_int
    struct deux_int ints = *(struct deux_int *) arg;
    int a = ints.a;
    int b = ints.b;