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

C++ Discussion :

Events asynchrones en C++


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut Events asynchrones en C++
    Bonjour,
    Je fais un jeu complexe et multithreadé. J'ai décidé de faire communiquer les différents threads de manière asynchrone et générique par un système d'events. Mais j'ai l'impression d'avoir construit une usine a gaz, et j'ai peur que la performance finale ne soit très affectée par ce système.

    Les particularités de mes besoins sont qu'un même event doit pouvoir être multicasté sur plusieurs threads différents, et doit être effacé proprement quand tout le monde l'a traité.

    Je suis donc parti sur une classe Event qui ressemble a cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Event
    {
    private:
       unsigned m_refCount;
    protected:
       Event();
       virtual ~Event();
    public:
       void grab();
       void release();
       unsigned getCount();
    };
    je dérive ensuite event autant que nécessaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class InputEvent : public Event;
    class KeyboardEvent : public InputEvent;
    class KeyboardKeyEvent : public KeyboardEvent;
    class GameEvent : public Event;
    ...
    Je créé ensuite des classes EventReceiver et EventSender afin de gérer le routage et le stockage des events, ainsi que le comptage des référence. Elles seront templatées afin que la file puisse ne traiter qu'une catégorie d'events plus ou moins précise.

    Quand je recois un event, j'utilise typeid et dynamic_cast pour récupérer les informations.


    Ce design est idéal en terme de fonctionnalités, je sais que ce système d'events s'adaptera à tout ce que je vais lui balancer. par contre, entre le RTTI (dynamic_cast, destructeur virtuel) et le comptage de références, j'ai bien peur que ca ne soit beaucoup trop intensif. Il y a aussi le problème de la fragmentation mémoire, car j'aurais beaucoup d'events créés et détruits. Je pensais utiliser un allocateur pour limiter les dégâts.

    D'une manière générale, mon approche est elle réaliste ? Existe t il des optimisations afin d’alléger la charge ? Qu'utilisez vous pour transmettre des informations entre threads dans des programmes complexes ?

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,

    Pour les événements j'ai l'habitude de voir dans les bibliothèques un union avec un discriminant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    struct
    {
          enum TypeEvent{CLAVIER, SOURIS};
          union
          {
                    struct Clavier{}clavier;
                    struct Souris{}souris;
           };
           TypeEvent typeEvent;
    };
    Pourquoi chaque évent doit-il être traité par chaque thread? N'est-ce pas plutôt un problème de conception?
    Si tes threads partages trop de ressources, ils vont se bloquer les uns les autres constamment et ils ne seront au final presque aussi performant qu'un seul thread.

  3. #3
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Pour les événements j'ai l'habitude de voir dans les bibliothèques un union avec un discriminant :
    C'est le système que j'avais mis en place au début. Le problème de ce système, c'est que pour ajouter un nouveau type d'event, il faut modifier une classe centrale, et tout recompiler. J'aimerais que des systèmes puissent créer de nouveaux types d'events selon leurs besoins sans avoir besoin de changer le code du coeur du moteur, mais en utilisant des "canaux" génériques.
    L'approche avec les structs est d'une manière générale très 'C' et j'essaie justement de trouver mieux. C'est un bon fallback si ce que j'aimerais ne marche pas.

    Citation Envoyé par Neckara Voir le message
    Pourquoi chaque évent doit-il être traité par chaque thread? N'est-ce pas plutôt un problème de conception?
    Si tes threads partages trop de ressources, ils vont se bloquer les uns les autres constamment et ils ne seront au final presque aussi performant qu'un seul thread.
    Tous les events ne sont pas traités par chaque thread, mais peut être traité dans plusieurs, juste ceux qui en ont besoin.
    Dans un jeu vidéo, il y a beaucoup de ressources partagées. Faire toutes les communications sous forme d'events permet justement d'éviter qu'ils ne partagent un état. L'idée est que chacun garde les infos dont il a besoin sous la forme la plus pratique pour sa tache, et ils se tiennent au courant des changements. Et ce de manière asynchrone, justement pour ne pas bloquer.

  4. #4
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Serait-il possible d'avoir un diagramme ou une présentation expliquant le rôle de chaque thread, ainsi qu'un exemple de fonctionnalité entraînant des échanges entre thread (exemple : gestion des collisions?) afin de mieux comprendre ce que tu fais ?

  5. #5
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut
    Heu j'ai ca sur un paquet de papier, mais ça reste partiel. Il y a des systèmes où j'ai une vague idée, mais sans avoir mis ça sur papier car je ne les développerais pas avant un bail.
    Coté modèle, le concept général est d'avoir chaque unité du jeu potentiellement dans un thread différent. En fait j'utilise un scheduler simple, on lui donne un nombre de threads, on lui balance les unités et il les répartit la charge entre les threads disponibles.
    Coté vue, Il y aura un thread graphique, chaque unité le tient au courant de ses changements par l'envoi d'un event contenant la position, les infos d'apparence, etc...
    Coté contrôleur, le clavier/souris seront dans le thread graphique, le joystick et autres inputs louches dans leur thread a eux. Ils envoient des events (appui de touche, etc..) a un contrôleur qui transformera ça en commande (avancer, tourner a droite, tirer...) qui sera envoyée à l'unité contrôlée.

    C'est simplifié, mais c'est l'esprit.

  6. #6
    screetch
    Invité(e)
    Par défaut
    il y a quand meme pas mal d'optimisations possibles, ca depend de tes contraintes

    deja, si tu elimines le dynamic_cast et que tu appelles seulement une methode virtuelle, ca sera ca de gagne (les dynamic_cast sont tres tres chers, surtout ceux qui echouent) (enfin ils l'etaient en 2007 quand j'ai ete confronte au probleme)

    pourquoi un dynamic_cast? pourquoi pas un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class IEvent
    {
      virtual void execute() = 0;
    };
     
    class MouseEvent : public IEvent
    {
      virtual void execute() /*override*/;
    };
    sinon, est-ce que le premier evenement traite est toujours le premier envoye (une FIFO) ou bien est-ce que les evenements peuvent etre traites dans un ordre aleatoire?

    j'ai deja realise un scheduler, qui demarre N threads (N le nombre de processeurs). Les "evenements" dont tu parles sont chez moi des taches, chaque tache a une methode virtuelle. Le resultat n'est pas horrible dans la mesure ou chaque tache a un peu de boulot a faire, cela compense l'appel de methode virtuelle.

    selon tes contraintes (ordre aleatoire, ou bien certains evenements sont assignes a certains threads particuliers) il y a des optimisations possibles, mais commencer avec une methode virtuelle n'est pas mauvais.

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 151
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Rewpparo Voir le message
    Coté modèle, le concept général est d'avoir chaque unité du jeu potentiellement dans un thread différent. En fait j'utilise un scheduler simple, on lui donne un nombre de threads, on lui balance les unités et il les répartit la charge entre les threads disponibles.
    Coté vue, Il y aura un thread graphique, chaque unité le tient au courant de ses changements par l'envoi d'un event contenant la position, les infos d'apparence, etc...
    Coté contrôleur, le clavier/souris seront dans le thread graphique, le joystick et autres inputs louches dans leur thread a eux. Ils envoient des events (appui de touche, etc..) a un contrôleur qui transformera ça en commande (avancer, tourner a droite, tirer...) qui sera envoyée à l'unité contrôlée.
    Je trouve que ça fait beaucoup de thread, et surtout beaucoup trop.

    Lors de mon passage dans le jeu-vidéo, on utilisait au total 4 threads il me semble
    - le thread principal
    - le thread de rendu
    - un thread pour le chargement et streaming des ressources
    - un thread audio

    Multiplier les thread ne fera qu'alourdir la logistique du logiciel, et surtout : quel intérêt ?
    Que chaque unité ait son propre thread ça semble sexy, mais va synchroniser le tout, c'est la galère.
    Alors que faire un update du dt sur chaque unité à chaque fois que nécessaire est enfantin. Et toutes tes unités évoluent du même dt.
    Idem pour les entrées clavier/joystick etc... quel intérêt réel ?! Le mieux étant de traiter la pile d'évènements à chaque évolution du dt.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

Discussions similaires

  1. WebMethod avec un event (retour asynchrone)
    Par LaurentC33 dans le forum Services Web
    Réponses: 0
    Dernier message: 18/02/2015, 16h51
  2. [CF 2.0][Windows Mobile 6.1] Event asynchrone
    Par thibaud dans le forum Windows Mobile
    Réponses: 0
    Dernier message: 14/05/2010, 18h58
  3. DLL TCP Asynchrone et delegate/event
    Par marso dans le forum C#
    Réponses: 1
    Dernier message: 03/09/2008, 19h05
  4. architecture d'un programme client/serveur asynchrone (win)
    Par Heimdall dans le forum Développement
    Réponses: 2
    Dernier message: 05/09/2003, 23h59
  5. Réponses: 6
    Dernier message: 25/03/2002, 21h11

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