15-12-2006 13:42:12
- smeagol
- Membres
- Date d'inscription:
- Messages: 34
- IP: 195.221.49.79
- Courriel
je reposte mon header qui permet de gérer des thread sout linux et windows.
#ifndef MY_THREAD_H
#define MY_THREAD_H
//Ces macros servent à uniformiser certaines fonctionnalités entre Windows et Linux.
#ifdef WIN32 //macro version Windows
# include <windows.h>
//definition des threads
# define callback_t unsigned long __stdcall
# define thread_t HANDLE*
# define thread_create(thrd, fct, param) thrd = new HANDLE;\\
*(thrd) = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(fct),(param),0,NULL)
# define thread_delete(thrd) CloseHandle(*(thrd));\\
delete (thrd);
# define thread_wait_close(thrd) WaitForMultipleObjects(1, *thrd, TRUE, INFINITE)
//definition des semaphores et mutex
# define mutex_t CRITICAL_SECTION
# define mutex_init(mutex) InitializeCriticalSection((mutex))
# define mutex_lock(mutex) EnterCriticalSection((mutex))
# define mutex_unlock(mutex) LeaveCriticalSection((mutex))
# define mutex_delete(mutex) DeleteCriticalSection((mutex))
# define semaphore_t HANDLE
# define semaphore_init(sema, max, place) ((sema) = CreateSemaphore(NULL, (max), (place), NULL))
# define semaphore_lock(sema) WaitForSingleObject((sema), INFINITE)
# define semaphore_unlock(sema) ReleaseSemaphore((sema), 1, NULL)
# define semaphore_delete(sema) CloseHandle(sema)
#else //macro version Linux
//definition des threads
# include <pthread.h>
# define callback_t void *
# define thread_t pthread_t*
# define thread_create(thrd, fct, param) (thrd) = new pthread_t;\\
pthread_create((thrd), NULL, (fct), (param))
# define thread_delete(thrd) delete (thrd);
# define thread_wait_close(thrd) pthread_join(*thrd, NULL)
//definition des semaphores et mutex
# include <semaphore.h>
# define mutex_t pthread_mutex_t *
# define mutex_init(mutex) (mutex) = new pthread_mutex_t;\\
pthread_mutex_init ((mutex), NULL)
# define mutex_lock(mutex) pthread_mutex_lock((mutex))
# define mutex_unlock(mutex) pthread_mutex_unlock((mutex))
# define mutex_delete(mutex) pthread_mutex_destroy((mutex));\\
delete ((mutex))
# define semaphore_t sem_t*
# define semaphore_init(sema, max, place) (sema) = new sem_t;\\
sem_init ((sema), (max), (place))
# define semaphore_lock(sema) sem_wait((sema))
# define semaphore_unlock(sema) sem_post((sema))
# define semaphore_delete(sema) sem_destroy((sema));\\
delete ((sema))
#endif
#endifPour commencer un thread est un outils capable de lancer des exécution parallèles de code dans un même programme.
________________
| |
| Code Principal |
|________________|
|
intruction...
| ________________
| | |
execution du thread -> | Code du thread |
| |________________|
| |
| |
intruction... intruction...
| |
| |
|-----------------------|
|
Fin du progComme le dit l'autre tuto les thread sont à éviter tant qu'une exécution séquentiel est possible.
Mais pour un moteur 3d je dirais qu'ils sont conseillés surtout si il y a un moteur physique.
Je m'explique vous avez remarqué que les processeurs récents on tous des dual-corps. Et bien chaque thread s'exécute sur un corps différent se qui permet un gain énorme en performance.
Bien sur les threads ne sont pas a utilisés à la légère a cause des ressources critiques. Vous avez bien plusieurs processeurs mais qu'une seul Mémoire RAM. Et si 2 threads tentent d'accéder à la même partie de la mémoire et bien il risque de ne pas avoir les résultats voulus. Et même de faire planter le programme.
Je ne vais pas vous faire un court sur les risques des ressources critiques et vous demande de me croire sur parole que ceci est très dangereux pour un programme fiable.
Pour éviter de rentrer a plusieurs dans une zone critique il existe des fonctions de mise en attente. Les mutexs et le semaphores. Vous me dites "Je peux le faire moi même avec une variable global booléenne" Mais je vous répond que non car imaginé que pendant que vous tester votre variable et que vous changer d'état la variable, le processeur permute de thread. Vous risquez de rentrer à deux dans la zone critique et la de planter ou créer des erreurs dans votre programme.
Voici un petit programme simple avec l'utilisation des mutexs.
#include <iostream>
#include "mythread.h"
//creation du mutex
mutex_t mut;
mutex_t io;
void trace(int x)
{
//Vue que trace est appeler par un thread
//et qu'elle utilise les entrers sorties
//il faut utiliser un autre mutex
//ATTENTION voici la zone critique seule un thread à le droit
//d'utiliser l'ES
mutex_lock(io);
printf("x = %d\
", x);
mutex_unlock(io);
//Fin de zone critique
//un thread en file d'attente peut rentrer
return;
};
callback_t maFonc(void* x)
{
//recastage de x
int* intX = (int*)
//ATTENTION voici la zone critique seule un thread à le droit
// de modifier la veleur de X
mutex_lock(mut);
//multiplication de x par lui même
*intX = *intX * *intX;
mutex_unlock(mut);
//Fin de zone critique
//un thread en file d'attente peut rentrer
trace(*intX);
return NULL;
};
int main()
{
//Création de x
int x;
//initialisation du mutex
mutex_init(mut);
mutex_init(io);
//Creation des threads
thread_t thrd[10];
int i;
for(i = 0; i < 10; i++)
thread_create(thrd[i], maFonc, &x);
//attente de la fermeture des threads
for(i = 0; i < 10; i++)
thread_wait_close(thrd[i]);
//destruction des threads et du mutex
for(i = 0; i < 10; i++)
thread_delete(thrd);
mutex_delete(mutex);
mutex_delete(io);
printf("\
\
X Final = %d\
", x);
return 0;
};Par contre il y a une règle de syntaxe qui ne va pas dans se programme. Il est important de s'imposer que seul les fonctions callback et celle qui créer le thread doivent utiliser des mutexs. deonc le code serait mieux ainsi:
#include <iostream>
#include "mythread.h"
//creation du mutex
mutex_t mut;
void trace(int x)
{
printf("x = %d\
", x);
return;
};
callback_t maFonc(void* x)
{
//recastage de x
int* intX = (int*)
//ATTENTION voici la zone critique seule un thread à le droit
// de modifier la veleur de X
mutex_lock(mut);
//multiplication de x par lui même
*intX = *intX * *intX;
trace(*intX);
mutex_unlock(mut);
//Fin de zone critique
//un thread en file d'attente peut rentrer
return NULL;
};
int main()
{
//Création de x
int x;
//initialisation du mutex
mutex_init(mut);
//Creation des threads
thread_t thrd[10];
int i;
for(i = 0; i < 10; i++)
thread_create(thrd[i], maFonc, &x);
//attente de la fermeture des threads
for(i = 0; i < 10; i++)
thread_wait_close(thrd[i]);
//destruction des threads et du mutex
for(i = 0; i < 10; i++)
thread_delete(thrd);
mutex_delete(mutex);
printf("\
\
X Final = %d\
", x);
return 0;
};Pour finir les semaphores.
Je ne vais pas poster de code car il fonctionne comme les mutexs. À la seul différence c'est que, dans le create_semaphore, 'max' représente le nombre maximum de thread qui on le droit de rentrer dans la zone critique.
Et place est le nombre au quels sont déjà rentrer dans le semaphore.
je mexplique:
create_semaphore(sema, 10, 2);10 processus auront le droit de rentrer dans le semaphore mais comme place = 2 seulement 8 pourront après l'initialisation. Donc si on fait un ...
create_semaphore(sema, 10, 10);Aucun thread ne pourra rentrer dans la zone critique tant que l'on n'a pas fait un semaphore_unlock.
Astuce: create_semaphore(sema, 1, 0); est donc un mutex
- --------------------------------------------------------------------------------------
PS : Je ne dit pas que cet header est parfait et sans bug mais je l'utilise personnellement et je n'est jamais eu un seul bug dessus.
Voilà à vos questions
Hors ligne
16-12-2006 08:21:29
- Jerry Kan
- Membres
- Date d'inscription:
- Messages: 265
- IP: 82.243.77.149
- Courriel
super bien détaillé ton tuto,
je pense que je vais me servir de ton header,
merci ![]()
Hors ligne
04-01-2007 09:54:10
- Jerry Kan
- Membres
- Date d'inscription:
- Messages: 265
- IP: 82.243.77.149
- Courriel
Je suis en train d'essayer ca depuis un moment ce matin,
en fait je n'arrive pas a faire marcher le tout (pas testé sous linux), je suis sous code::block (meme erreur sous dev) , j'avoue que je suis pas tres habitué a windows (beuurk ^^ ) donc je rate peut etre un truc tout simple
j'ai créé un le .h et le .cpp comme tu le décrit, je clique sur le truc pour compiler et la :
Project : Console application
Compiler : GNU GCC Compiler (called directly)
Directory : C:\\Documents and Settings\\laurent\\Bureau\ h2\\
--------------------------------------------------------------------------------
Switching to target: default
Compiling: main.cpp
In file included from main.cpp:2:
mythread.h:29: error: expected constructor, destructor, or type conversion before '=' token
mythread.h:29: error: expected `,' or `;' before '=' token
main.cpp: In function `long unsigned int maFonc(void*)':
main.cpp:23: error: cannot convert `CRITICAL_SECTION' to `_CRITICAL_SECTION*' for argument `1' to `void EnterCriticalSection(_CRITICAL_SECTION*)'
main.cpp:27: error: cannot convert `CRITICAL_SECTION' to `_CRITICAL_SECTION*' for argument `1' to `void LeaveCriticalSection(_CRITICAL_SECTION*)'
main.cpp:32: warning: converting to non-pointer type `long unsigned int' from NULL
main.cpp: In function `int main()':
main.cpp:41: error: cannot convert `CRITICAL_SECTION' to `_CRITICAL_SECTION*' for argument `1' to `void InitializeCriticalSection(_CRITICAL_SECTION*)'
main.cpp:51: error: invalid conversion from `void*' to `void* const*'
main.cpp:51: error: initializing argument 2 of `DWORD WaitForMultipleObjects(DWORD, void* const*, BOOL, DWORD)'
main.cpp:57: error: `mutex' undeclared (first use this function)
main.cpp:57: error: (Each undeclared identifier is reported only once for each function it appears in.)
main.cpp:62:3: warning: no newline at end of file
Process terminated with status 1 (0 minutes, 1 seconds)
10 errors, 1 warningsla premiere des erreurs corresponds a la ligne :
*(thrd) = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(fct),(param),0,NULL)éventuellement tu aurait un zip d'un exemple comprenant les sources et le .cbp (ou le .dev) ?
Hors ligne
04-01-2007 10:21:04
- kedu
- Modérateurs

- Date d'inscription:
- Messages: 155
- IP: 212.194.103.106
- Courriel
Je n'ai pratiquement pas de notion en c++ donc ne m'en veut pas si je me plante mais pour ta ligne d'erreur :
*(thrd) = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(fct),(param),0,NULL)
Est-ce que CreateThread est une méthode quelconque de la classe ou le constructeur de la classe ?
Si c'est un constructeur, il faudrait mettre new après le =. (si new est la bonne syntaxe en c++)
Désolé par avance si je suis à côté de la plaque :-/
Hors ligne
04-01-2007 10:29:00
- Jerry Kan
- Membres
- Date d'inscription:
- Messages: 265
- IP: 82.243.77.149
- Courriel
a priori non, puisque c'est un exemple qui ne comprends pas de classe,
comme c'est une ligne de la grosse macro du .h, je suis un peu perdu,
mais je suis arrivé a faire autrement en utilisant la librairie pthread.dll, et avec laquelle on peut porter les threads linux sans changement de code, je suis en train de mettre a jour mon tuto (l'autre tuto) pour expliquer comment faire
Hors ligne
04-01-2007 10:50:24
- kedu
- Modérateurs

- Date d'inscription:
- Messages: 155
- IP: 212.194.103.106
- Courriel
Ah oui intéressant ça ! Si ça peut éviter de s'arracher les cheveux à faire des conversions (très passionnantes) de code...
Hors ligne
04-01-2007 13:10:37
- smeagol
- Membres
- Date d'inscription:
- Messages: 34
- IP: 86.211.84.203
- Courriel
Je ne vois pas trop. je ne peut pas te faire un exemple pour windows car je ne l'est plus. Mais ces macro son utilisé en simplifier dans mk_socket (disponible sur l'upload). Et sa fonctionne sous win et linux. Enfin bon si tu trouve la source bug. envoie ta version corriger du header.
Hors ligne
05-01-2007 09:38:57
- Jerry Kan
- Membres
- Date d'inscription:
- Messages: 265
- IP: 82.243.77.149
- Courriel
je pense qu'une partie du problème viens du formatage fait par un copier coller
les lignes du type :
# define semaphore_delete(sema) sem_destroy((sema));\\
delete ((sema));doivent etre remplacée par
# define semaphore_delete(sema) sem_destroy((sema)); delete ((sema));parce que pour une raison obscure, lors du copier coller, le caractere "\\" a perdu son "pouvoir" a faire poursuivre sur la meme ligne
quand j'arrive a refaire marcher le tout je fait un zip et je l'upload
Hors ligne
05-01-2007 12:13:24
- Jerry Kan
- Membres
- Date d'inscription:
- Messages: 265
- IP: 82.243.77.149
- Courriel
voila j'ai terminé le debug, ca fonctionne (testé windows et linux),
j'ai uploadé le zip avec le .h et les deux exemples ici
attention, j'ai modifié plusieurs choses dans le .h et .cpp donc ca marche un peu différemment qu'a l'origine, notamment coté utilisation des pointeurs,
Hors ligne
05-01-2007 22:09:00
- Copland
- Modérateurs
- Date d'inscription:
- Messages: 657
- IP: 90.5.239.86
- Courriel Site web
Merci beaucoup pour le zip, je charge ça car je vais en avoir besoin...pas dans l'immédiat mais c'est prévu à mon programme donc un grand merci pour votre aide
.
Config : I5 2400, ATI HD6870 1Go DDR5, 4Go DDR3.
Single Boot : Windows Seven.
Hors ligne
13-01-2007 02:28:49
- Copland
- Modérateurs
- Date d'inscription:
- Messages: 657
- IP: 90.11.178.7
- Courriel Site web
Waow !! Que du bonheur vraiment merci, je viens de l'utiliser sous Windows pour gérer ma physique et ça a l'air de bien fonctionner !
Encore merci à vous pour se code et ses explications
.
Config : I5 2400, ATI HD6870 1Go DDR5, 4Go DDR3.
Single Boot : Windows Seven.
Hors ligne



