Forum de la communauté SFML

Aide => Système => Discussion démarrée par: Samuel Proulx le Mai 14, 2012, 11:38:58 pm

Titre: [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 14, 2012, 11:38:58 pm
Bonjour à tous et à toutes :)

J'ai une variable qui est partagée entre plusieurs threads :
std::list<DataUser> m_clients[32][18];
 
Bon vous savez les problèmes que ça apporte si l'un est en lecture et qu'en même temps, un autre thread supprime une entrée de la list.

J'ai donc trouvé les deque qui, dans ce cas, font pointer l'itérateur qui pointe sur rien (à cause d'une suppression) sur la donnée précédente dans la liste.

Voilà, seulement, comment être alerté que l'itérateur a changé ainsi dans une boucle ? Est-ce que on peut simplement stocker l'itérateur précédent et le comparer à l'itérateur actuel ? Ainsi, si les deux itérateurs sont équivalent, ça veut dire qu'il y a eu une suppression et du coup, faut pas exécuter le code qui va suivre...

Merci de votre patience et bonne journée ! 8)
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 15, 2012, 08:12:30 am
Citer
J'ai donc trouvé les deque qui, dans ce cas, font pointer l'itérateur qui pointe sur rien (à cause d'une suppression) sur la donnée précédente dans la liste.
Ouhla... je ne sais pas pourquoi ça réagit comme ça chez toi, mais ne base pas ton code sur ce comportement.

std::deque, std::list ou n'importe quel autre conteneur standard, n'est pas thread-safe. Si tu as des accès concurrents il faut les éliminer avec un mutex ou autre. C'est la seule façon correcte de gérer ce genre de situation.

Ce que tu voulais faire là c'est du bricolage ultra-bancal.
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 15, 2012, 01:15:18 pm
D'accord et est-ce que la SFML intègre des mutex qui permettent de faire un model multiple-reader/single writer ?

Voici un code avec les mutex normal pour ce genre de problème, mais ça semble vraiment bordélique...

thread_lecture1
{
    mutex_écriture.lock();   //Si on écrit, alors on attend
    mutex_écriture.unlock(); //Écriture fini, on peut lire
    mutex_lecture1.lock();   //Lecture1 en cours... on lock le mutex
    //Plein de code...
    mutex_lecture1.unlock(); //Lecture terminée, on débloque le mutex de lecture1
}
thread_lecture2
{
    mutex_écriture.lock();   //Si on écrit, alors on attend
    mutex_écriture.unlock(); //Écriture fini, on peut lire
    mutex_lecture2.lock();   //Lecture2 en cours... on lock le mutex
    //Plein de code...
    mutex_lecture2.unlock(); //Lecture terminée, on débloque le mutex de lecture1
}
thread_écriture
{
    mutex_écriture.lock();   //On veut écrire, on lock le mutex d'écriture
    mutex_lecture1.lock();   //On s'assure que lecture1 n'est pas en cours
    mutex_lecture1.unlock(); //On le débloque, car le but n'est pas de le bloquer
    mutex_lecture2.lock();   //On s'assure que lecture2 n'est pas en cours
    mutex_lecture2.unlock(); //On le débloque, car le but n'est pas de le bloquer
    //Plein de code...
    mutex_écriture.unlock(); //Écriture terminée, on débloque le mutex de d'écriture
}
 

Sans compter qu'il va falloir mettre tout ça à jour si un jour j'ajoute un nouveau lecteur...

Quelle serait la meilleure solution sans sortir du cadre de la SFML ? On m'a présenté par exemple boost::shared_mutex, mais je ne suis vraiment pas intéressé à utiliser une autre bibliothèque que la SFML dans ce projet.

Merci et bonne journée ;)
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 15, 2012, 01:18:28 pm
C'est quoi ce merdier ? ;D (nan, bon, j'ai compris ce que tu veux faire -- mais la manière dont tu le fais, c'est bizarre)

Utilise un seul mutex pour tout le monde. Ce ne sera pas le plus optimal que tu puisses faire, mais si tu as vraiment besoin de faire des choses poussées (ce qui n'est pas forcément le cas) alors de toute façon SFML est insuffisante.
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 15, 2012, 01:28:03 pm
Effectivement, mon but est de faire en sorte que les deux threads (ou plus) de lecture puissent être actif ensemble et que quand le writer veut écrire, il attend que les lectures soient finies et il commence à écrire...

Je devrai donc utiliser autre chose apparemment... Je vais faire ma mutex personnalisée dans ce cas ;D

ps. Je ne fais pas des choses si poussées, juste un peu :P , mais les performances de cette application sont plus qu'importantes. Un thread ne doit absolument pas s'arrêter si ce n'est pas nécessaire.
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 15, 2012, 01:40:24 pm
Dans ce cas je ne sais pas si tu pourras faire un truc optimisé avec uniquement des mutexs. Il te faudrait en plus de ça au moins des entiers atomiques.

Si tu le peux, utiliser la nouvelle bibliothèque standard (C++11) serait une bonne alternative.
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 15, 2012, 02:05:42 pm
Il semblerait que code::blocks intègre cela, mais qu'il faut l'activer manuellement, car c'est encore considéré comme expérimental...(probablement très stable tout de même)

Je vais aller voir de ce côté la semaine prochaine, là je pars à Ottawa en compétition de musique (MusicFest Canada). À bientôt et merci !  :)
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 15, 2012, 02:08:28 pm
Citer
Il semblerait que code::blocks intègre cela
En fait ce serait plutôt dépendant de la version de GCC que Code::Blocks utilise ;)
Et là tu peux prendre une 4.7 ou une 4.8, qui gère très bien le dernier standard.

Bonne chance pour la compet' ;)
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 15, 2012, 11:09:29 pm
merci :) (j'ai internet à l'hôtel  ;D)

Est-ce que le module network peut supporter 1000 clients ou pas ? certains m'ont dit qu'il n'était pas adapté pour faire ce genre de chose... Seulement, si je regarde blablaland par exemple, ils ont dit eux-même que chacun des mondes étaient un serveur physique...

Qu'en penses-tu ?

De plus, étant donné que mon lock pour l'écriture consiste toujours à supprimer simplement une entrée dans un list, est-ce que ça ne serait pas plus simple de faire boucler le thread jusqu'à ce que ça soit disponible ?

Autrement dit, reprendre le code précédant en changeant les mutex pour des booléen et simplement faire un while(écriture_en_cours);
//plein de code de lecture...

Qu'en penses-tu ? Car dans mon cas, il ne restera jamais très longtemps bloqué puisque il va attendre simplement une lecture (très très rapide donc) ou la lecture va attendre l'écriture (très rapide puisqu'on supprime juste un "pointeur" dans la list).

Merci et bonne journée  :)
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 16, 2012, 07:37:48 am
Citer
Est-ce que le module network peut supporter 1000 clients ou pas ?
Ca dépend de ce que tu fais avec ;)

Citer
De plus, étant donné que mon lock pour l'écriture consiste toujours à supprimer simplement une entrée dans un list, est-ce que ça ne serait pas plus simple de faire boucler le thread jusqu'à ce que ça soit disponible ?
Oui c'est une bonne idée, d'ailleurs ça s'appelle un spin-lock. Mais ça requiert des entiers atomiques (pour la variable écriture_en_cours), que le nouveau standard fournit mais pas SFML.
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 16, 2012, 06:52:15 pm
Certaines personnes sur le SdZ m'ont dit qu'on pouvait pas écouter plus de 64 sockets avec la SFML à cause de FD_SETSIZE dans une structure FD_SET... ? C'est quoi ça ? Tu pourrais m'expliquer ? :o

Ensuite, aurais-tu un article qui parle des entiers atomiques ou me l'expliquer parce que je comprends pas pourquoi on ne pourrait pas simplement utiliser un booléen... ?
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 16, 2012, 10:23:44 pm
Citer
Certaines personnes sur le SdZ m'ont dit qu'on pouvait pas écouter plus de 64 sockets avec la SFML à cause de FD_SETSIZE dans une structure FD_SET... ? C'est quoi ça ? Tu pourrais m'expliquer ?
sf::SocketSelector utilise en interne une liste à taille fixe définie par l'OS, et sous Windows effectivement ça peut être 64. Il y a déjà un ticket pour améliorer ça.

Citer
Ensuite, aurais-tu un article qui parle des entiers atomiques ou me l'expliquer parce que je comprends pas pourquoi on ne pourrait pas simplement utiliser un booléen... ?
Il y a sûrement plein d'articles sur le net.
Très simplement : tu tentes de protéger une variable partagée entre plusieurs threads (ta liste) avec... une autre variable partagée (le booléen). Tu te mors la queue, à un moment il te faut une primitive qui soit thread-safe sinon tu ne feras toujours que déplacer le problème vers une autre variable. Et les entiers atomiques sont thread-safe, comme leur nom l'indique.
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 17, 2012, 04:17:57 am
D'accord je comprends très bien ce que tu veux dire :) (j'ai pas trouvé de tuto en français du moins sur les entier atomique)

Mais voilà, un entier atomique doit forcément consommer plus en ressource puisqu'il est thread-safe..

Ça serait bien plus léger d'avoir 3 booléens et de changer l'état de ceux-ci et de vérifier leur état si nécessaire non ? Je sais que mon application va toujours posséder un writer et deux readers alors même si mon code n'est pas optimisé à des fins de modification, il va vraiment l'être au niveau des performances non ?

Pas besoin de m'expliquer qu'il s'agit sûrement d'une mauvaise méthode de voir les choses ou je ne sais quoi... J'aimerais simplement savoir si ma façon de faire est effectivement plus efficace que les entier atomique :)

Merci et bonne journée ! ;D
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 17, 2012, 10:25:07 am
Citer
Mais voilà, un entier atomique doit forcément consommer plus en ressource puisqu'il est thread-safe..
Non justement : ils sont implémentés via des instructions du processeur (une seule par opération). Donc ça ne coûte pas un copec. De nos jours tous les processeurs supportent ce genre d'opérations.
Les entiers atomiques sont à la base de pas mal de mécanismes plus complexes. Ils sont utilisés pour implémenter ce que l'on appelle les conteneurs "lock-free" -- ie. qui sont thread-safe sans nécessiter de bloquer les threads.

Et peu importe la manière dont tu veux implémenter les choses autrement, ce ne sera jamais robuste si ce n'est pas basé à un moment où un autre sur une primitive thread-safe.
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 17, 2012, 02:01:27 pm
D'accord, merci beaucoup pour tes conseils et explications : ça devient donc très intéressant comme solution les entiers atomiques :)
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 17, 2012, 03:11:48 pm
Petite question : j'ai finalement trouvé le foutu fichier des atomiques dans mon compilateur ;D (c'est dans les lib c++ bits/atomic_0.h ou atomic_2.h)

Je me pose donc la question : quelle est la différence ? dans les fichiers, c'est écrit que le _0.h est «never lock-free» et l'autre, atomic_2.h, et bien le contraire : «always lock-free».

Selon ce que tu m'as dit, s'ils sont lock-free, ça veut dire que ça ne bloquera pas les threads... Je devrais donc utiliser le _0 ou le _2 ? Puisque dans un cas, ça le bloque et c'est ce que je veux et dans l'autre, ça ne le bloquera pas et je devrai donc faire du spin-lock.. ?

Que me conseilles-tu ?

Merci et bonne journée :)
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 18, 2012, 08:05:54 pm
Moi je te conseillerait plutôt d'utiliser ton compilo en mode C++11 et les en-têtes standards qui vont avec. Ceux que tu as trouvés ne le sont pas.
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 20, 2012, 03:47:06 am
Petit problème : c'est GCC 4.4.1 qui est avec code::blocks semblerait-il puisque le nom du dossier de GCC dans mingw c'est 4.4.1....

Ça doit être possible de changer la version de GCC je suppose... Je cherche comment faire parce que j'ai téléchargé GCC 4.7.0, mais j'ai aucune idée comment le foutre dans mon compilo haha  ;D
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 20, 2012, 09:33:19 am
C'est très simple : dans les options de compilateur, tu dois avoir un truc genre "toolchain", il suffit de changer les chemins pour mettre ceux de ton dossier 4.7.0.
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 21, 2012, 02:04:16 am
Merci j'ai trouvé c'est dans Settings/Compiler and Degugger/Toolchain executables pour ceux que ça intéresse.

Petite question comme ça : si je ne définie pas de selector et que je me contente de faire du socket.isReady sur la liste des sockets (puisqu'il faut les stocker à l'extérieur du selector maintenant), ça règle le problème qui vient de windows là ? (les 64 sockets dans le selector max)

Merci et bonne journée :)

Et je suis enfin revenue des compétitions haha :)

Sur tous nos ensembles (jazz 1, 2, 3, 4, 5, ensemble 1, 2, 3-4-5, 4-5, 2-3) seul le jazz 1 n'a pas eu une mention or :) (les chiffres représentent en fait l'année scolaire (secondaire au québec soit de 12 à 17 ans))

Si tu veux écouter les pièces qu'on a joué, j'te recommande notre meilleure : http://www.youtube.com/watch?v=0CjCAIfAs00&feature=related (http://www.youtube.com/watch?v=0CjCAIfAs00&feature=related)

EDIT

Petit problème : la méthode isReady vient du selector ! haha  ;D :P

As-tu une solution simple pour se problème sans pour autant passer toutes les sockets en mode non-bloquante ? ???
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 21, 2012, 07:59:55 am
Je n'ai pas vraiment de solution non, les autres façons de faire impliquent soit des sockets non-bloquantes, soit des threads. Mais tu comptes vraiment avoir plus de 64 sockets ?
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 21, 2012, 03:11:20 pm
Ben il y a quelques jours, je t'ai demandé si le module pouvait supporter 1000 clients/sockets/connexions... Alors oui j'ai l'intention d'utiliser plusieurs centaines de sockets, mais pas plus de 1000 ;)

Il faudrait que la méthode isReady existe pour les sockets, mais je sais pas si c'est possible (j'ai jamais regarder le code interne d'un selector).

Je vais alors me contenter de mettre les sockets non bloquantes, ça sera plus simple ainsi :)
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 21, 2012, 03:25:32 pm
Citer
Alors oui j'ai l'intention d'utiliser plusieurs centaines de sockets
Juste par curiosité, tu codes quoi en fait ?

Citer
Il faudrait que la méthode isReady existe pour les sockets, mais je sais pas si c'est possible (j'ai jamais regarder le code interne d'un selector).
Non ce n'est pas possible. Sinon c'est carrément toute la classe sf::SocketSelector qui n'aurait aucun intérêt.

Citer
Je vais alors me contenter de mettre les sockets non bloquantes, ça sera plus simple ainsi
Je pense aussi :)
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Samuel Proulx le Mai 21, 2012, 04:31:52 pm
Si tu me juges pas, alors tu peux lire la suite... ;D

Je suis en train de faire un MMOG similaire à DarkOrbit (http://www.darkorbit.fr/)
vidéo (http://www.youtube.com/watch?v=RQAIapHloX0&feature=channel&list=UL)

La différence entre ce projet et un MMORPG, tu le comprends bien, est le fait que l'équipement est très limité (par exemple, dans FLYFF, il y a plus de 4 000 items existants tandis que DarkOrbit en a à peine quoi... 150 ? En plus, lorsque ce jeu est sortie au tout début, on pouvait compter exactement 37 items en incluant les vaisseaux.

Tu peux donc comprendre qu'au niveau graphique, créer 37 items voire moins en 2D, c'est pas la fin du monde selon moi :)

En ce qui concerne le réseau/serveur, c'est sûrement la partie la plus dur à faire (le client c'est long, mais pas si compliqué, on s'entend). Et dans un sens, je n'ai pas vraiment le choix d'utiliser la SFML sur le serveur puisque c'est sûr que je vais l'utiliser pour le client là... (je vais pas commencer à formater les Packet que je veux envoyer, tu l'as déjà fait pour moi ! ;D ;)).

Si ça t'intéresse, voici une petite image qui explique rapidement comment je compte m'y prendre :
(http://uploads.siteduzero.com/thb/378001_379000/378177.png) (http://uploads.siteduzero.com/files/378001_379000/378177.png)

Bien sûr, chaque ZONE et serveur de connexion a un accès local à chacun d'entre eux : une ZONE doit pouvoir communiquer avec n'importe quelle ZONE pour transférer le client et le serveur de connexion a un accès à toutes les ZONE pour la redirection du client.

Donc s'il y a des trucs importants que je dois savoir sur le module réseau de la SFML.... ;)

Il n'y a aucun jeu que je n'aime plus que celui-ci. Malheureusement, BigPoint ont vu qu'ils avaient le monopole et ont commencé à sortir plein de trucs super cher et que seuls ceux qui payent beaucoup (100$+ par semaine) peuvent avoir.

Depuis, j'ai arrêté de jouer et c'est ça qui me pousse à tenter mon coup en créant ma propre version de ce jeu. J'aimerais que les anciens joueurs de ce jeu puissent rejouer gratuitement. C'est ce que je veux faire.

Il faudra payer un abonnement super cher par année pour pouvoir jouer  :P : 5$ ;D

Bien sûr, le prix reste à vérifier... Je pourrais tout aussi bien offrir 1 mois pour 5$, 6 mois pour 10$ et 1 an pour 15$. Peu importe, c'est une somme maudite à côté de ce qu'il faut investir dans DO pour être fort.
Titre: Re : [SFML2] Besoin d'un petit conseil thread/list.erase
Posté par: Laurent le Mai 21, 2012, 04:55:02 pm
Merci pour les détails. C'est assez ambitieux, surtout comme tu l'as remarqué pour la partie réseau. Donc bon courage :)

En ce qui concerne le module réseau de SFML, il est assez rudimentaire (et bas niveau) comparé à ce qu'on trouve sur le marché. Je souhaite qu'il te soit suffisant, mais si tu vois que ce n'est pas le cas alors ne t'acharne pas, et utilise une vraie bibliothèque (voire un moteur) dédiée au réseau.