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

Haskell Discussion :

[HGL]Problème de multithreading


Sujet :

Haskell

  1. #1
    Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Juin 2007
    Messages
    111
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Juin 2007
    Messages : 111
    Points : 64
    Points
    64
    Par défaut [HGL]Problème de multithreading
    Salut !

    Cela fait quelques temps que j'apprend Haskell, le plus dur étant de se débarasser de son style impératif . Je voulais, pour l'expérience, faire un système de sélection de groupe (comme dans les jeux de stratégies à la Age Of Empire) : en gros, un rectangle qui se dessine selon une sélection faite à la souris. Mon code est le suivant (très court) :
    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
     
    module Main where
     
    import Graphics.HGL
    import Control.Concurrent(forkIO,killThread)
     
    rect               :: Point -> Point -> Graphic
    rect (x,y) (x1,y1) = polygon [(x,y),(x1,y),(x1,y1),(x,y1)]
     
    waitMove w s       = do e <- getWindowEvent w
                            case e of
                              MouseMove{pt=p} -> do drawInWindow w $ rect s p
                                                    waitMove w s
                              Button{pt=p,isLeft=left,isDown=down}
                                | not down    -> return () -- button released
                              _               -> waitMove w s
     
    waitPress w        = do e <- getWindowEvent w
                            case e of
                              Button{pt=p,isLeft=left,isDown=down}
                                | down -> waitMove w p
                              _        -> waitPress w
     
    loop               :: Window -> IO ()
    loop w             = do waitPress w
                            loop w
     
    main               :: IO ()
    main               = runGraphics $
                         withWindow_ "Select" (600,600) $ \w->do
                         id <- forkIO (loop w)
                         getKey w
                         killThread id
    (désolé pour la structure du module peu travaillée, mais je voulais faire ça rapidement [avant de tomber sur mon problème] ).

    Si je n'utilise pas forkIO, aucun problème : le rectangle se dessine selon les mouvements de la souris, et s'arrête dès que je relâche le bouton. Mais si j'utilise le threading (ce qui serait le cas si un jour je voulais inclure ce module dans un logiciel), rien ne va plus : les clics sont rarement pris en compte, le relâchement de la souris presque jamais, etc...

    Alors de deux choses l'une :
    • soit le multithreading n'est pas adapté à ce que je veux faire, auquel cas je me demande bien comment les développeurs font pour que le jeu continue pendant la sélection
    • soit je ne sais pas me servir du multithreading, ce qui est probable puisque je n'ai aucune expérience en la matière

    Notez également que j'ai tenté d'utiliser forkOS à la place, mais sans succès.

    J'espère que vous pourrez m'aider,

    <Zer0>

  2. #2
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Tu as essayé d'employer plutôt les "par*" fournis par le module Graphics.HGL(.Utils) ?

    Sinon, plutôt que de faire du multithreading, utiliser getWindowTick et maybeGetWindowEvent pourrait être une meilleure solution.

    --
    Jedaï

  3. #3
    Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Juin 2007
    Messages
    111
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Juin 2007
    Messages : 111
    Points : 64
    Points
    64
    Par défaut
    Tu as essayé d'employer plutôt les "par*" fournis par le module Graphics.HGL(.Utils) ?
    A vrai dire, je ne vois pas trop comment je pourrais m'en servir, puisque ce que je souhaite faire est assez "hiérarchique" (je ne peux pas dessiner tant que la souris n'a pas bougé, et les mouvements de la souris ne m'intéressent pas tant qu'il n'y a pas eu de clic). Le truc, c'est que la gestion des évenements et du dessin doit être transparente dans le cas où j'incluerais mon module dans un programme plus important, d'où le multithreading.

    Sinon, plutôt que de faire du multithreading, utiliser getWindowTick et maybeGetWindowEvent pourrait être une meilleure solution.
    Mais je crois que je n'ai pas le choix. Les actions de dessin et de détection des évenement ne doivent pas bloquer le programme. Pour reprendre l'exemple de Age Of Empire, le jeu n'a pas à s'arrêter le temps que je fasse ma sélection !
    Je pourrais adopter le système de « Game Loop », mais à l'origine ce module n'est pas destiné à un jeu et je souhaitais qu'il soit indépendant (et puis, disons-le franchement, un système de game loop doit être particulièrement moche, implanté avec un langage fonctionnel). Je trouvais que lancer un thread pour chaque intéraction de l'utilisateur avec la fenêtre était une bonne approche, mais les différents threads sont manifestement trop peu synchronisés entre eux pour pouvoir en tirer quelque chose :/ ...

    Désolé si j'ai compris de travers ton message .


    ---
    EDIT : Ah, je crois comprendre pourquoi tu parlais des par*. Tu veux dire que je pourrais lancer en parallèle ma fonction loop avec d'autres fonctions d'affichage ? Si oui, cela poserais deux problèmes :
    • l'ordre du dessin ne serais pas déterminé, par exemple (restons dans AoE), les soldats pourraient être dessinés tantôt par dessus l'aire de sélection, tantôt en dessous :/
    • je présume que les fonctions par* reposent sur le multithreading, et que je serais confronté au même "bug" (edit #2 : je confirme, utilisation de forkIO)

    Par ailleurs, si tu les sais, cela m'intéresserait de savoir pourquoi cela ne marche pas, je préfère voir ensuite pour les alternatives .

  4. #4
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    As-tu essayé de lancer ton programme avec +RTS -N2 ? Est-il compilé avec -threaded ?

    --
    Jedaï

  5. #5
    Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Juin 2007
    Messages
    111
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Juin 2007
    Messages : 111
    Points : 64
    Points
    64
    Par défaut
    J'ai bien compilé avec l'option threaded.
    lancer ton programme avec +RTS -N2
    Euh... kézako ?

  6. #6
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    C'est une option à donner à ton programme en le lançant pour qu'il emploie deux threads système (les threads en GHC sont des threads utilisateurs ultraléger, mais si tu compiles avec threaded et utilise +RTS -Nn, ces threads utilisateurs sont distribués sur des threads systèmes, ce système très performant te permet de combiner les avantages des threads utilisateur (ultraléger question mémoire et généralement plus performant) et des threads système (utilise plusieurs cores, préemption par l'OS)).

    (De mon côté j'ai essayé de tester, mais avec GHC6.8.3, HGL semble avoir d'autres problèmes...)
    --
    Jedaï

  7. #7
    Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Juin 2007
    Messages
    111
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Juin 2007
    Messages : 111
    Points : 64
    Points
    64
    Par défaut
    Ok, j'ai essayé mais cela n'a rien changé :/ ... Sinon j'utilise GHC 6.8.2, étrange vu sa notoriété que HGL ne supporte pas la dernière version .
    J'ai commencé à coder un système de game loop pour comparer, j'ai pas encore finis que ça prend déjà trois fois plus de place. Dommage (il était beau mon code !).

    EDIT : fini. Le code est pas _trop_ horrible, mais il me semble que les performances ne sont pas au rendez-vous (le programme rame à mort en mode DoubleBuffered :/ ). M'enfin ça doit être dû à ma machine, vu que j'ai pas l'accéleration 3D . Vais essayer de faire des binaires sous Win pour voir.

Discussions similaires

  1. Problème de multithreading
    Par amayesNewDev dans le forum Groovy
    Réponses: 1
    Dernier message: 03/11/2012, 22h28
  2. Problème serveur multithread
    Par asnaeb dans le forum C#
    Réponses: 4
    Dernier message: 01/04/2011, 15h49
  3. Réponses: 16
    Dernier message: 01/10/2010, 13h47
  4. Réponses: 8
    Dernier message: 04/03/2009, 14h39
  5. Réponses: 4
    Dernier message: 13/02/2008, 12h53

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