IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Rust Discussion :

[Rust] 1.77.2 -- condition variables


Sujet :

Rust

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 329
    Par défaut [Rust] 1.77.2 -- condition variables
    Greetings !!

    Je voudrais effectuer le portage d'une application initialiement écrite en C en Rust, mais l'implémentation des conditions variables me posent des soucis.

    Le programme doit lancer une série de threads qui se mettraient en attente et puis le thread principal après avoir "préparé le terrain" enverrait un signal à tous les threads en attente, ensuite ce même programme principal s'occuperait de récupérer les résultats...
    Ce dernier doit attendre que tous les threads aient terminé.

    Questions: je ne trouve pas d'exemples probants par rapport à ce que je voudrais faire, du coup je suis un peu démunis.
    Je bouquine mais rien ne me donne de piste précise: l'utilisation de Arc m'est complètement farfelue, même si apparemment c'est utile pour éviter les "race conditions"...

    A priori je ne devrais pas craindre de "race conditions" dans l'exécution de mon programme, l'important c'est que les threads se déclenchent à un instant 'T', c'est le plus important, les threads vont juste produire des données à travers le réseau mais pour le coup ils doivent
    démarrer "tous ensembles", pour "simuler" un "flood".

  2. #2
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 329
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
            let mut sys_time = SystemTime::now();
    	println!("DEBUG {}",sys_time.duration_since(UNIX_EPOCH).unwrap().as_nanos());
     
    	let mut cpt :u16 = 0;
     
    	let mut vectorhandle = Vec::new();
    	let donnees = Arc::new((Mutex::new(cpt),Condvar::new()));
     
    	for threadid in 0..MAXTHREADS
    	{
    		let clone_donnees = Arc::clone(&donnees);   // copier les données dans le bloc
    		let threadhandle = thread::spawn
    			(
    				move ||
    				{
    					let (verrou,cvar) = &*clone_donnees;        // récupérer les données empaquetées dans Arc
    					let mut donnees = verrou.lock().unwrap();
    					*donnees+=1;
    					let mut threadid= donnees.clone() as usize;
    					println!("Thread {} waiting...",threadid);
    					cvar.wait(donnees).unwrap();
    					println!("[{}] Launched !!",threadid);
    				}
    			);
    			vectorhandle.push(threadhandle);
    	}
     
    	let (verrou,cvar) = &*donnees;
    	let mut donnees= verrou.lock().unwrap();
     
    	// Signifier aux threads qu'ils peuvent se lancer...
     
    	cvar.notify_all();
    	thread::sleep(Duration::from_secs(MAXTHREADS as u64));
    Voilà le prototype... ici je n'ai pas le temps d'envoyer la "notification" aux threads, le programme se termine, le soucis c'est que je ne sais pas où placer le join() pour que le thread principal "attende" au moins que tous les threads soient lancés avant d'envoyer le signal "go" représenté
    par la condition variable... je suis en deadlock du coup vu que le thread ne se termine pas vu qu'il attend que le thread principal lui dise de continuer via la condvar.

    Du coup, vu que ça ne fonctionne pas du tout comme en C, je suis perdu... par exemple avec la solution présente de manière tout à fait aléatoire sur, par exemple, 50 threads il n'y en a des fois 2, des fois 5 qui se lancent réellement... ce qui est assez mauvais.
    Ma solution en C fonctionne, très bien d'ailleurs (sauf sous windows je ne sais pas pourquoi, peut-être le scheduler est plus merdique que sous Linux) mais je voulais essayer de voir ce que cela donnerait en Rust en cross-compile.
    Je suis plutôt mal embarqué :{

  3. #3
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour,

    Citation Envoyé par hurukan Voir le message
    Du coup, vu que ça ne fonctionne pas du tout comme en C, je suis perdu... par exemple avec la solution présente de manière tout à fait aléatoire sur, par exemple, 50 threads il n'y en a des fois 2, des fois 5 qui se lancent réellement... ce qui est assez mauvais.
    Ma solution en C fonctionne, très bien d'ailleurs (sauf sous windows je ne sais pas pourquoi, peut-être le scheduler est plus merdique que sous Linux) mais je voulais essayer de voir ce que cela donnerait en Rust en cross-compile.
    C'est normal que ce code Rust ne fonctionne pas. Mais, si on écrit le même algorithme en C avec pthreads, cela ne devrait pas fonctionner non plus.

    Plus précisément, l'algorithme actuel ne fonctionne que dans le cas où tous les threads générés ont appelé std::sync::Mutex::lock / pthread_mutex_lock avant le thread principal. Alors, dans chacun de ces threads générés, l'appel de std::sync::Condvar::wait / pthread_cond_wait bloque le thread en débloquant le mutex en attendant la notification. Alors, le thread principal peut arriver jusqu'à std::sync::Condvar::notify_all / pthread_cond_broadcast qui envoie la notification. Le thread principal doit alors libérer le mutex. Ton code en C appelle sûrement pthread_mutex_unlock. Ton code en Rust appelle implicitement std::sync::MutexGuard::drop à la fin de la portée du MutexGuard, donc après le sleep. Chacun des threads notifiés essaie de bloquer le mutex (c'est ce que fait std::sync::Condvar::wait / pthread_cond_wait avant de rendre la main au code appelant) puis, après acquisition du mutex, continue son exécution, puis débloque le mutex via std::sync::MutexGuard::drop / pthread_mutex_unlock.

    Dans les autres cas, il y a deadlock.

    En plus, cet algorithme ne garantit pas que les threads générés attendent bien le "go" avant de faire le traitement principal. En effet, selon les documentations de std::sync::Condvar::wait et pthread_cond_wait, le thread peut quand même se réveiller ("spurious wakeup") sans avoir été notifié.

    C'est probablement pour ça que le code en C de départ ne marche pas sur Windows.

Discussions similaires

  1. [PDO] Requête PDO avec condition variable
    Par int85 dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 15/04/2015, 16h45
  2. Fonction conditionnelle à conditions variables
    Par Autodidacte92 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 14/08/2013, 17h13
  3. [Toutes versions] If avec un nombre de conditions variables
    Par Boris_Gem dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 08/09/2010, 09h40
  4. Simuler les conditions variables
    Par khazna dans le forum Windows
    Réponses: 4
    Dernier message: 22/02/2009, 14h36
  5. Réponses: 4
    Dernier message: 28/10/2008, 11h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo