Threads

Signaler
Messages postés
8
Date d'inscription
jeudi 30 mars 2006
Statut
Membre
Dernière intervention
18 juillet 2006
-
Messages postés
8
Date d'inscription
jeudi 30 mars 2006
Statut
Membre
Dernière intervention
18 juillet 2006
-
Bonjour,

En fait je travaille sur un projet ou je dois écrire une thread qui
accède à des données sous formes de liste chainees et doit mettre à
jour la liste . Elle doit s'éxecuter en tache de fond.

J'ai deja implementer la liste chainee, et j'ai un pb avec la thread je
vois pas trop comment bloquer l'acces au ressources (la liste) pour que
les lectures et ecritures dans la liste soient synchronisées.



Si une ame charitable (un big boss du c) pouvait me sortir de cette
galère et me donné une idée de comment coder cette thread ca serè
vrément bien.

Merci à mon sauveur.

Ciao, bye

7 réponses

Messages postés
688
Date d'inscription
mercredi 6 avril 2005
Statut
Membre
Dernière intervention
2 juin 2006
1
bon, je tiens a préciser que je suis un boss en rien, mais je suis ds les threads wxWIDGETS ces temps ci;

pour windows, je pense bien mais brunews corrigera surmt lol :

dans l'entry de toin thread

CMutex m_mutex;

m_mutexFiles.Lock();

ton instruction

m_mutex.Unlock();

sous windows, je ne sais pas si c'est ce que tu veux, sinon, regarde les semaphores


@+;
satellite34

http://www.rootscommunity.com/</FON< body>
Messages postés
688
Date d'inscription
mercredi 6 avril 2005
Statut
Membre
Dernière intervention
2 juin 2006
1
dsl, j'oubliait les critical section aussi, qui soint trés importantes si multithread;



@+;
satellite34

http://www.rootscommunity.com/</FON< body>
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
12
err normalement sous l'API windows ya toute une gamme de fonctions qui servent au thread mais je sais pas du tout celle que tu cherche. Tu peut toujours aller voir ici. Ça parle des thread et des process

___________________________________________
Les plus grands esprits trouvent toujours une solution
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
21
Au 1er abord je dirais un event (CreateEvent() 1 fois au début du prog), c'est ultra simple pour la synchro
HANDLE hev = 0
hev = CreateEvent(0, 1, 0, 0); // MANUEL, NON SIGNALE
SetEvent(hev); // MISE EN SIGNALE
ResetEvent(hev); // REMISE EN NON SIGNALE
WaitForSingleObject(hev, INFINITE); // ATTENTE SIGNALEMENT

Ensuite comme toujours faudrait voir le prog pour savoir ce qui convient le mieux.

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Messages postés
1491
Date d'inscription
dimanche 19 novembre 2000
Statut
Modérateur
Dernière intervention
7 juillet 2014

Ultra simple :

InitializeCriticalSection(&sync) //Au début du programme
DeleteCriticalSection(&sync) //Fin du programme
EnterCriticalSection(&sync) //Bloquer les autres threads
LeaveCriticalSection(&sync) //Débloquer les autres threads

Sinon CreateEvent comme BN dit, mais on peut les mettres en mode automatique si on veut encore simplifier.

A+

http://vbaddons.free.fr
MSN : x_men_40(
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
21
Le mode manuel serait justement bien pour lui ici, permettrait que l'un dise à l'autre d'y aller et vice versa.
Je procède ainsi pour l'envoi de paquets dans un sender ftp et c'est tip top.

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Messages postés
8
Date d'inscription
jeudi 30 mars 2006
Statut
Membre
Dernière intervention
18 juillet 2006

Salut tout le monde,


Merci pour toute les infos que vous m' avez donne, mais etant encore debutant je vois pas trop comment implantes les threads ainsi que leur synchronisation dans mon programme.


En fait j'ai realise un programme serveur SIP (VoIP) qui doit recevoir des messages des clients, les analyser puis enregistrer des donnees relatives au different client dans un liste chainee (cette liste doit etre mise a jour regulierement en tache de fond par une thread) puis les relayer vers les clients destinataires.


J'ai fait un programme de mise a jour dans un thread mais j'ai pas encore reussi a l'integrer dans le programme serveur et je suis perdu.

Si une personne saurait comment faire le rassemblement de mes deux program (faudrait que le serveur soit execute par une thread) il me serait d,un grand secours.
Merci à mon sauveur.
Ciao, bye

//////////////////////////////////////////////////////////CODE SOURCE SERVEUR////////////////////////////////////////////////////////////////////////////////////////
#include "biblio.h"
#include "stdafx.h"
#pragma comment(lib,"ws2_32.lib")



WSADATA initialisation_win32; // Variable permettant de récupérer la structure d'information sur l'initialisation
int erreur; // Variable permettant de récupérer la valeur de retour des fonctions utilisées
int tempo; // Variable temporaire de type int
int nombre_de_caractere; // Indique le nombre de caractères qui a été reçu ou envoyé
char buffer[65535]; // Tampon contennant les données reçues ou envoyées
SOCKET id_envoi; // Identifiant de la socket
SOCKET id_recept; // Identifiant de la socket
SOCKADDR_IN info_envoi; // Déclaration de la structure des informations lié au serveur
SOCKADDR_IN info_recept;

char separateur2[N];
char tmp1[N];
char *mots1;
char adIP[N];
char ad_IP[N];
int flag=0;
/* flag
0->init
1->register
2->invite
3->


*/
list<tab_SIP> maliste;
list<tab_SIP>::iterator itliste;
list<tab_SIP>::iterator itlistetmp[N];//iterateur=pointeur de liste d'entier
tab_SIP elt1;
//affichage des chps des elets de la liste
void affichElem(list<tab_SIP> maliste,list<tab_SIP>::iterator itliste){
printf("\n");
cout << (*itliste).adIP << endl;//<<endl=saut de ligne
cout << (*itliste).adSIP << endl;//<<endl=saut de ligne
cout << (*itliste).timer << endl;//<<endl=saut de ligne
}



void InitPaq (PaqSip *p1){
strcpy(p1->typmsg,"REGISTER");
strcpy(p1->domain,"ief.org");
strcpy(p1->via," ");
strcpy(p1->from,"emetteur");
strcpy(p1->to,"serveur");
strcpy(p1->CallID," ");
strcpy(p1->timer,"0");
}
void AffichPaq(PaqSip p1){
printf("\n");
printf("typmsg=%s \n",p1.typmsg);
printf("domain=%s \n",p1.domain);
printf("via=%s \n",p1.via);
printf("from=%s \n",p1.from);
printf("to=%s \n",p1.to);
printf("CallID=%s \n",p1.CallID);
printf("timer= %s \n",p1.timer);
}
//paq en ligne->paq en struct
void InvMesLign(PaqSip *p1,char ligne[]){
char *mots;
char separateur[]="#";
int cptMot;
//recup le 1er mot de la chaine
mots=strtok(ligne,separateur);//etablir chaine et recup le premier mot

strcpy(p1->typmsg,mots);
cptMot=0;

while(mots!=NULL){

mots=strtok(NULL,separateur);//recup les prochains mots
cptMot++;
switch (cptMot){
case 1:
strcpy(p1->domain,mots);
break;
case 2:
strcpy(p1->via,mots);
break;
case 3:
strcpy(p1->from,mots);
break;
case 4:
strcpy(p1->to,mots);
break;
case 5:
strcpy(p1->CallID,mots);
break;
case 6:
strcpy(p1->timer,mots);
break;
default:
mots=NULL;//securite!
break;
}
}
}
//extrait le type du msg (/ex REGISTRAR)
void ExtraitMsg (PaqSip *p1){
char tmp[N];
char *mots;
char separateur[]=" ";
strcpy(tmp,p1->typmsg);

//recup le 1er mot de la chaine
mots=strtok(tmp,separateur);//etablir chaine et recup le premier mot



if(!strcmp(tmp,"REGISTER")) {
flag=1;
}
else if (!strcmp(tmp,"INVITE")) {
flag=2;

}
else if (!strcmp(tmp,"OK180")){

flag=3;
}
else if (!strcmp(tmp,"OK200")){

flag=4;
}
else if (!strcmp(tmp,"ACK")) {
flag=
}
else if (!strcmp(tmp,"BYE")) {
flag=6;
}
else {printf("msg inconnu! \n"); }


}
void Ack(PaqSip *p1){
char temp[N];
//rempli chmps typmsg
strcpy(p1->typmsg,"OK200");
strcpy(temp,p1->typmsg);
strcat(temp," ");
strcat(temp,version);
strcpy(p1->typmsg,temp);
//rempli chmps from :non modif


//rempli chmps to non :modif


//rempli chmps timer
strcpy(p1->timer,0);
}



void Recoit(){

erreur=WSAStartup(MAKEWORD(2,2),&initialisation_win32);
id_recept=socket(AF_INET,SOCK_DGRAM,0);
info_recept.sin_family=AF_INET; // Indiquez l'utilisation d'IPV4
info_recept.sin_addr.s_addr=INADDR_ANY; // Indiquez l'adresse IP de votre serveur
info_recept.sin_port=htons(33333); // Port TCP 33333 à destination du serveur
erreur=bind(id_recept,(struct sockaddr*)&info_recept,sizeof(info_recept));
tempo=sizeof(info_recept); // Passe par une variable afin d'utiliser un pointeur
nombre_de_caractere=recvfrom(id_recept,buffer,1515,0,(struct sockaddr*)&info_recept,&tempo);
buffer[nombre_de_caractere]=0; // Permet de fermer le tableau après le contenu des data, car la fonction recvfrom ne le fait pas
}



char *MesLign(PaqSip *p1){
char temp[N];


strcpy(temp,p1->typmsg);
strcat(temp,"#");
strcat(temp,p1->domain);
strcat(temp,"#");
strcat(temp,p1->via);
strcat(temp,"#");
strcat(temp,p1->from);
strcat(temp,"#");
strcat(temp,p1->to);
strcat(temp,"#");
strcat(temp,p1->CallID);
strcat(temp,"#");
strcat(temp,p1->timer);
strcat(temp,"#");

return temp;
}


void Envoi(PaqSip p1,char adIP[]){
erreur=WSAStartup(MAKEWORD(2,2),&initialisation_win32);
//envoi du register
id_envoi=socket(AF_INET,SOCK_DGRAM,0);
info_envoi.sin_family=AF_INET; // Indiquez l'utilisation d'IPV4
info_envoi.sin_addr.s_addr=inet_addr(adIP); // Indiquez l'adresse IP de votre serveur
info_envoi.sin_port=htons(33334); // Port TCP 33333 à destination du serveur
//printf("Data %s\n\n",MesLign(&p1));
strcpy(buffer,MesLign(&p1));// Copie la chaine de caractère dans buffer


nombre_de_caractere=sendto(id_envoi,buffer,strlen(buffer),0,(struct sockaddr*)&info_envoi,sizeof(info_envoi));
erreur=closesocket(id_envoi);



}


int main (int argc, char* argv[]){




printf("\n********************************** SERVEUR ***********************************\n");
while (1) {
PaqSip p1,p2,p3;
int flag2=0;
Recoit();

printf("\nVoici les donnees recues: %s\n",buffer);
//printf("Received packet from %s\nData: %s\n\n", inet_ntoa(info_recept.sin_addr)/*, ntohs(info_recept.sin_port)*/, buffer);
strcpy(ad_IP,inet_ntoa(info_recept.sin_addr));
printf("ad IP enregistre=%s \n",ad_IP);
InitPaq (&p1);
InvMesLign(&p1,buffer);
ExtraitMsg (&p1);


switch (flag){
case 1://->registrar init paq des 3 chps
strcpy( elt1.adIP,ad_IP);
strcpy( elt1.adSIP,p1.from);
elt1.timer=atoi(p1.timer);
maliste.push_back(elt1);
itliste = maliste.begin();
do{
affichElem(maliste,itliste);
if (!strcmp((*itliste).adSIP,p1.to)) strcpy(adIP,(*itliste).adIP);
itliste++;
}while(itliste!=maliste.end());
flag=0;
itliste = maliste.begin();//init le pt au debut de la liste
strcpy(p1.typmsg,"OK200");
Envoi(p1,adIP);//
printf("RENVOIE:::::::%s; IPdest=%s\n",buffer,adIP);
break;
case 2: //->Invite
//parcours liste+affich elemts+met à jour la liste avec les @sip

itliste = maliste.begin();//init le pt au debut de la liste

do{
if (!strcmp((*itliste).adSIP,p1.to)){
strcpy(adIP,(*itliste).adIP);
strcpy(p1.via,adIP);//recup ip du dest pour ack
flag2=1;//recup IP ds table de ad sip du dest
}
itliste++;//iterateur++
}while(itliste!=maliste.end());//parcours la liste tant qu'on est pas à la fin
if(flag2==1){
strcpy(separateur2,"@");

strcpy(p1.typmsg,"INVITE");
strcat(p1.typmsg," ");
strcpy(tmp1,p1.to);
mots1=strtok(tmp1,separateur2);//etablir chaine et recup le premier mot
strcat(p1.typmsg,mots1);
strcat(p1.typmsg,separateur2);
strcat(p1.typmsg,adIP);
strcat(p1.typmsg," ");
strcat(p1.typmsg,version);


printf("redirection du Invite\n");
AffichPaq(p1);
flag=0;
Envoi(p1,adIP);
}else { flag=5;/*printf("flag5\n");getch();//pas ds la table*/
}
break;


case 3: //->ok180
//parcours liste+affich elemts+met à jour la liste avec les @sip
itliste = maliste.begin();//init le pt au debut de la liste
do{
if (!strcmp((*itliste).adSIP,p1.to)){
strcpy(adIP,(*itliste).adIP);
}
itliste++;//iterateur++
}while(itliste!=maliste.end());//parcours la liste tant qu'on est pas à la fin
flag=0;
Envoi(p1,adIP);
break;


case 4: //->ok200
//parcours liste+affich elemts+met à jour la liste avec les @sip
itliste = maliste.begin();//init le pt au debut de la liste
do{
if (!strcmp((*itliste).adSIP,p1.to)){
strcpy(adIP,(*itliste).adIP);
}
itliste++;//iterateur++
}while(itliste!=maliste.end());//parcours la liste tant qu'on est pas à la fin
flag=0;
Envoi(p1,adIP);
break;
case 5: //->ERREUR general 400
strcpy(adIP,inet_ntoa(info_recept.sin_addr));
strcpy(p1.typmsg,"ERREUR400");
AffichPaq(p1);
Envoi(p1,adIP);
case 6: //->bye
//parcours liste+affich elemts+met à jour la liste avec les @sip
itliste = maliste.begin();//init le pt au debut de la liste
do{
if (!strcmp((*itliste).adSIP,p1.to)){
strcpy(adIP,(*itliste).adIP);
}
itliste++;//iterateur++
}while(itliste!=maliste.end());//parcours la liste tant qu'on est pas à la fin
flag=0;
Envoi(p1,adIP);
break;


default :
break;
}
erreur=closesocket(id_recept);
}
#ifdef __WIN32__
system("PAUSE"); /* Pour la console Windows. */
#endif
return 0;
}
//////////////////////////////////////////////////////////CODE SOURCE MISE A JOUR///////////////////////////////////////////////////////////////////////////////
// TestThread.cpp : Defines the entry point for the console application.
//


#include "stdafx.h"
#include <windows.h>


#include <time.h>
#include <stdio.h>
#include <time.h>
#define expire 3600
#define raffr 10000


#include
#include <list>
#define N 256
int ACK=0;


using namespace std;


typedef struct PaqSip{

char typmsg[N];
char domain[N];
char via[N];
char from[N];
char to[N];
char CallID[N];
char heure_expiration[N];
}PaqSip;


typedef struct SIP
{
int heure_expiration;
char adIP[255];
char adSIP[255];
} SIP;


// Liste des correspondants enregistrés
list<SIP> maliste;//Liste chaine
list<SIP>::iterator itlistetmp[N];//iterateur=pointeur de liste d'entier


PaqSip p1;
SIP p3,p4,p5,p6;



void InitPaq (PaqSip *p1){
strcpy(p1->typmsg,"REGISTER");
strcpy(p1->domain,"ief.org");
strcpy(p1->via," ");
strcpy(p1->from,"sip:ouidi@ief.org");
strcpy(p1->to,"serveur");
strcpy(p1->CallID," ");
strcpy(p1->heure_expiration,"0");
}
void AffichPaq(PaqSip p1){
printf("\n");
printf("typmsg=%s \n",p1.typmsg);
printf("domain=%s \n",p1.domain);
printf("via=%s \n",p1.via);
printf("from=%s \n",p1.from);
printf("to=%s \n",p1.to);
printf("CallID=%s \n",p1.CallID);
printf("heure_expiration= %s \n",p1.heure_expiration);
}



/////////////////////////////////////////////////////
//mise à jour de la table evec les heure_expirations
/////////////////////////////////////////////////////


//affichage des chps des elets de la liste
void affichElem(list<SIP>::iterator itliste){
cout << (*itliste).adIP << endl;//<<endl=saut de ligne
cout << (*itliste).adSIP << endl;//<<endl=saut de ligne
cout << (*itliste).heure_expiration << endl;//<<endl=saut de ligne
}


void affichListeElem(list<SIP>::iterator itliste){
//affichage de la liste (/crs)
cout << "Liste" << endl;
itliste = maliste.begin();
do {
printf("\n");
affichElem(itliste);
itliste++;//iterateur++
}while(itliste!=maliste.end());//parcours la liste tant qu'on est pas à la fin
}


int HeureCourante(){
struct tm *t;
time_t timestamp;
int heure_courante=0;
timestamp = time (NULL);
t = gmtime(&timestamp);
heure_courante=((t -> tm_hour)*3600)+((t -> tm_min)*60)+t->tm_sec;
return heure_courante;
}


//parcours liste+affich elemts+met à jour la liste avec les heure_expirations
void MiseAJourTimer(list<SIP>::iterator itliste){
bool efface=0;
int i=0;
itliste = maliste.begin();//init le pt au debut de la liste
do{
if (((*itliste).heure_expiration-HeureCourante())<=0){
itlistetmp[i]=itliste;
efface=1;
i++;
}
itliste++;//iterateur++
}while(itliste!=maliste.end());//parcours la liste tant qu'on est pas à la fin

if (efface==1) {
while (i!=0){
maliste.erase(itlistetmp[i-1]);
printf("efface l'element car heure_expiration =0 \n\n");
i--;
}
}
}


//parcours liste+affich elemts+met à jour la liste avec les @sip
void MiseAJourSIP(list<SIP>::iterator itliste,char ad_IP[]){
itliste = maliste.begin();//init le pt au debut de la liste

do{
if (!strcmp((*itliste).adSIP,p1.from)){
strcpy((*itliste).adIP,ad_IP);
(*itliste).heure_expiration=HeureCourante()+3600;
}

itliste++;//iterateur++
}while(itliste!=maliste.end());//parcours la liste tant qu'on est pas à la fin


}


DWORD WINAPI ThreadFunc1( void* param)
{
list<SIP>::iterator itliste;
printf( "My thread ID is: %d\n", GetCurrentThreadId() );


do
{
Sleep(raffr);
affichListeElem(itliste);
MiseAJourTimer(itliste);
MiseAJourSIP(itliste,"192.192.192"/*nouvelleip*/);
affichListeElem(itliste);



//printf("Coucou 1\n : %d\n",GetCurrentThreadId());


}
while(true);


return 0;
}


DWORD WINAPI ThreadFunc2( void* param )
{
printf( "My thread ID is: %d\n", GetCurrentThreadId() );


int i=0;
do
{
Sleep(2000);
i++;
printf("Coucou 2\n : %d\n",i);
}
while(true);


return 0;
}



void main( void )
{
DWORD threadId;
HANDLE hThread1, hThread2;
int heure_expiration=0;
int temp=1;
//tests
InitPaq(&p1);
strcpy( p3.adIP,"255.255.255.2551");
strcpy( p3.adSIP,"@sip1");
p3.heure_expiration=1000000;
strcpy( p4.adIP,"255.255.255.2552");
strcpy( p4.adSIP,"@sip2");
p4.heure_expiration=43951;
strcpy( p5.adIP,"255.255.255.2553");
strcpy( p5.adSIP,"sip:ouidi@ief.org");
p5.heure_expiration=500000000;
strcpy( p6.adIP,"0.255.0.2556");
strcpy( p6.adSIP,"@sip6");
p6.heure_expiration=0;//


list<SIP>::iterator itliste;//iterateur=pointeur de liste d'entier


maliste.push_back(p3);
maliste.push_back(p4);
maliste.push_back(p5);
maliste.push_back(p6);



//création thread
hThread1 = CreateThread( NULL, 0, ThreadFunc1, NULL,
0, &threadId );



//HeureCourante();
//printf("====%d",heure_courante);//heure courante
//heure_expiration=HeureCourante()+expire;
//printf("====%d",HeureCourante());//heure courante

//printf("la date et l'heure courante sont : %s\n", ctime(&t));

// do{


//}while(ACK==0/*&&*/);



// hThread2 = CreateThread( NULL, 0, ThreadFunc2, NULL,
// 0, &threadId );




/* wait for the thread to finish */
WaitForSingleObject( hThread1, INFINITE );
// WaitForSingleObject( hThread2, INFINITE );


/* clean up resources used by thread */
CloseHandle( hThread1 );
//CloseHandle( hThread2 );
}