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

Langage C++ Discussion :

Appel d'une class template dans une callback appelé par un thread


Sujet :

Langage C++

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2012
    Messages : 8
    Points : 1
    Points
    1
    Par défaut Appel d'une class template dans une callback appelé par un thread
    Bonjour à tous.

    Je fait actuellement une classe son basée sur SDL_sound (projet d'étude)

    sound_manager.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<typename T, typename U>
    class   c_sound_manager : public c_singleton<c_sound_manager<T,U> >
    {
            friend class c_singleton<c_sound_manager<T,U> >;
            public:
     
            private:
                    c_sound_manager();
                    ~c_sound_manager();
    }
    main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include "sound_manager.hpp"
    enum    e_sound
    {
            SOUND_FIRE,
            SOUND_WATER
    };
     
    int     main(void)
    {
            c_sound_manager<e_sound, int>*   sound_manager = c_sound_manager<e_sound, int>::get_instance();
     
    //      l'utilisateur utilise la classe son
    }
    Voici ici la callback que j'indique au thread de la SDL, où je fais le mixage de son.

    sound_manager.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void*   callback_mix_audio(void* user_data, Uint8* stream, int len)
    {
    //      par contre ici je dois récupérer le singleton soit via le suer_data comme ça
            c_sound_manager<e_sound, int>*   sound_manager = static_cast<c_sound_manager<e_sound, int>* >(user_data);
    //      soit comme cela
            c_sound_manager<e_sound, int>*   sound_manager = c_sound_manager<e_sound, int>::get_instance();
    
    
    
    //      traitement du son
    }
    Et donc ce qui m'ennuis, c'est qu'il faut remettre les types template à l'appel du singleton ou au cast, mais cette callback n'est pas accessible à l'utilisateur, donc il devrait disposer des sources et ensuite re-compiler la callback.
    J'ai mis une solution alternative en attendant une meilleure, avec des typedefs comme cela.

    main.cpp
    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
    enum    e_sound
    {
            SOUND_FIRE,
            SOUND_WATER
    };
    typedef e_sound TYPE_1
    typedef int     TYPE_2
    #include "sound_manager.hpp"
     
    int     main(void)
    {
            c_sound_manager<e_sound, int>*   sound_manager = c_sound_manager<e_sound, int>::get_instance();
     
    //      l'utilisateur utilise la classe son
    }
    La classe son ne change pas, et ça donne ça dans la callback

    sound_manager.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void*   callback_mix_audio(void* user_data, Uint8* stream, int len)
    {
            c_sound_manager<TYPE_1, TYPE_2>*   sound_manager = c_sound_manager<TYPE_1, TYPE_2>::get_instance();
     
    //      traitement du son
    }
    Donc ça marche l'utilisateur n'a pas besoin des sources, juste d'une petite documentation, mais je voudrais savoir s'il existe une solution encore plus pratique.
    Car la il faut quand même definir les types template au dessus des typedefs et faire l'incude en dessous, je cherche au plus pratique.

    Avant cette classe son n'était pas template, à l'intérieur les deux types en question était des int mais c'est plus pratique comme ça pour nommer ses sons, au lieu d'avoir des nombres.

    Voila merci d'avance.

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Je ne suis pas sur d'avoir complètement compris ton problème (notamment qui écrit la callback et que peut elle voir).

    L'idée est probablement de faire du type erasure.

    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
    struct sound_handler
    {
    public:
    static void*   callback_mix_audio(void* user_data, Uint8* stream, int len)
    {
       reinterpret_cast<sound_handler*>(user_data)->mix_audio(stream,len);
    }
    private:
      virtual void mix_audio(Uint8* stream, int len)=0;
    };
     
    //
    template<typename T1, typename T2>
    struct concrete_sound_handler : public sound_handler
    {
    public:
    static void*   callback_mix_audio(void* user_data, Uint8* stream, int len)
    {
       reinterpret_cast<sound_handler*>(user_data)->mix_audio(stream,len);
    }
    private:
      virtual void mix_audio(Uint8* stream, int len){
            c_sound_manager<e_T1, T2>*   sound_manager = c_sound_manager<T1, T2>::get_instance();
    // 
    }
    };
     
    //
    Dans la même veine, une autre solution est de créer une indirection via un std::function qui irait vers une fonction ayant visibilité sur les objets adéquats à son traitement.

    Enfin, l'indétrônable article d'Emmanuel dès qu'on sort le mot singleton

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2012
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Bonjour merci pour votre réponse.

    C'est une même personne qui écrit la callback et la classe son (moi même), c'est plutôt une librairie son qui nous permettra de rajouter du son dans nos futurs projets d'études très rapidement donc les fichiers de cette lib seront compiler quand nous feront un nouveau projet.

    Dans une fonction membre de la class c_sound_manager j'initialise la carte son avec la fonction SDL_OpenAudio( , ); et je dois indiquer dans ses arguments une callback void (*callback)(void *userdata, Uint8 *stream, int len); que le thread de la SDL appellera constamment, dans cette callback je récupère mon singletont c_sound_manager pour avoir accès aux son actuellement en lecture pour pouvoir les mixer dans le Uint8 *stream.

    Le problème est que ma classe son est template donc je dois redonner les types template dans cette callback pour récupérer le singletont mais vu que c'est le développeur utilisateur de la lib son qui décide de ses types et qu'il n'a pas accès à la callback qui est déjà compilée ça pausé un problème.

    Ce problème à vrais dire réside dans le fait de devoir donner une callback non membre, du coup quand on est dans la callback on ne sait plus du tout quels sons est en lecture et on doit récupérer les infos dans le singleton.

    Je regarde attentivement les liens que tu ma donner, et merci pour l'idée de mettre la callback dans une structure je pense que ça me donne une idée, j'essaye ça.





    Voici une meilleur vue d'ensemble ça devrais être plus clair:


    FICHIER: main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include "sound_manager.hpp"
    enum    e_sound
    {
            SOUND_FIRE,
            SOUND_WATER
    };
    
    int     main(void)
    {
            c_sound_manager<e_sound, int>*   sound_manager = c_sound_manager<e_sound, int>::get_instance();
    
    //      l'utilisateur utilise la classe son
    }

    FICHIER: sound_manager.hpp
    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
    36
    37
    38
    39
    40
    #ifndef __SOUND_MANAGER_HPP__
    #define __SOUND_MANAGER_HPP__
    
    void    callback_mix_audio(void* user_data, Uint8* stream, int len);
    
    template<typename T, typename U>
            class   c_sound_manager : public c_singleton<c_sound_manager<T,U> >
            {
                    friend class c_singleton<c_sound_manager<T,U> >;
                    public:
                             int     init_carte_sond(int frequence, Uint16 formart, Uint8 nb_channel, Uint32 size_buffer);
                    private:
                            c_sound_manager();
                            ~c_sound_manager();
    
                            SDL_AudioSpec    obtained;
                            SDL_AudioSpec    desired;
            };
    
    template<typename T, typename U>
            int     c_sound_manager<T,U>::init_carte_sond(int frequence, Uint16 formart, Uint8 nb_channel, Uint32 size_buffer)
            {
                    this->desired.freq = frequence;
                    this->desired.format = format;
                    this->desired.channel = nb_channel;
                    this->desired.sample = size_buffer;
                    this->desired.callback = callback_mix_audio;
                    this->desired.userdata = NULL;
                    SDL_OpenAudio(&this->desired, &this->obtained);
            }
    
    void    callback_mix_audio(void* user_data, Uint8* stream, int len)
    {
            c_sound_manager<e_sound, int>*   sound_manager = c_sound_manager<e_sound, int>::get_instance();
    //      l'utilisateur n'est pas sensé venir mettre ses types template ici, c'est ça le problème
    
    //      traitement du son
    }
    
    #endif

  4. #4
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2012
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Pour mon idée ça tombe à l'eau, je lit tes liens.

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2012
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Re bonjour,

    J'ai fini de lire, si j'ai bien compris le type erasure c'est le fait de pouvoir stocker des objets de types différents dans un même conteneur grâce au polymorphisme ? Je connaissais cette méthode et si c'est bien cela je ne vois pas comment cela peux régler mon problème, sinon toutes mes excuses.

    L'article du singleton ma pas mal intéressé ^^, je suis bien d'accord avec lui, c'est la première fois que je fait un singleton durant mes projets j'ai déjà pensé à en faire avant sur d'autres classes mais j'ai bien vue que cela était inutile et c'est encore vrais sur ma classe c_sound_manager.

    Mais que je retire ou pas le singleton le problème reste là, dans la callback je devrais caster le void* userdata et il me faudra les types template de la classe c_sound_manager que l'utilisateur aura choisi.

    Je suis toujours à la recherche de solutions.

  6. #6
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 580
    Points
    218 580
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Dans mon projet, j'ai déjà fait de la surcouche de SDL et de sa partie son. Voilà ce que cela a donné : http://code.google.com/p/openawars/s...2FNative%2FSDL
    (Voir notamment les classes SDL_Sound / SDL_SoundEngine)

    Moi, je me demande pourquoi votre classe pour le son a besoin du template ... qu'en faites vous ?
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2012
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Bonjour, merci beaucoup je vais regarder votre projet.

    Je commence à me dire que cette idée de template est de trop mais voila ce que j'en fait:


    Avant que ma classe soit template:

    Quand l'utilisateur ajoute un son il lui attribut une key de stockage:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int     c_sound_manager::add_sound(const char* path, int key_stock);

    Ensuite quand l'utilisateur souhaite lire un son il selectionne le son desiré avec cette key de stockage et lui donne une key de lecture:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int     c_sound_manager::listen_sound(int key_stock, int key_play, d'autres aguments ...);

    Et avec ces deux key il peux soit sélectionner un son stocker pour le lire ou le supprimer soit sélectionner un son en train d'être lut:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int     c_sound_manager::delete_sound(int key_stock);
    void    c_sound_manager::set_volume_sound_playing(int key_play, int volume);
    void    c_sound_manager::stop_sound_playing(int key_play);
    Et donc j'aurais bien aimé que l'utilisateur puisse choisir les type des key donc je template les key_stock et key_play.
    comme une enum pour la key de stockage tel que:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    enum    e_sound
    {
            SOUND_FIRE,
            SOUND_WATER
    }
    C'est plus sympa que des int.
    Et je précise que ces key sont les key utilisées dans les std::map de stockage de sons et la map de lecture de sons.

    Je pense que cette idée de key est pas mal, qu'en pensez vous ?
    Mais après les template sur les key cela vas plutôt compliquer l'utilisation de ma classe au finale.

  8. #8
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 580
    Points
    218 580
    Billets dans le blog
    120
    Par défaut
    J'ai un système similaire de clés, mais à la place des int, j'utilise des std::string. Ceux-ci à la base sont les chemins menant aux fichiers et comme un fichier == un son (du moins chez moi), j'estime la clé unique (après, j'ai une banque de données, qui associe donc la clé avec le son correspondant et je peux faire mes get comme je le souhaite). (Tout cela, c'est toujours dans le même projet).

    Mon avantage, c'est que je n'ai pas un enum à mettre à jour afin d'avoir un son supplémentaire

    De plus, dans votre dernière explication, je ne vois plus du tout l'utilité du template, il est passé où ?
    Ah, et un truc que j'ai pas compris, pourquoi il y a une clé de stockage et une de lecture ? Celle de lecture, c'est pour récupérer l'instance en cours d'être jouer (et donc si on le souhaite, de la mettre en pause ?)

    En plus, dans tout cela, c'est l'utilisateur qui donne toujours la clé, ce qui me rend un peu perplexe, du fait que l'on donne un peu trop de contrôle à l'utilisateur.
    Un modèle plus classique serait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int addSound(const char* path);
    Où, la fonction renvoie un ID sur le son (et donc la classe fait la correspondance) et non que ce soit l'utilisateur qui définisse la clé lui même.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  9. #9
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2012
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Re bonjour,

    C'est les key que je templates; la key de lecture sert à pouvoir lire plusieurs fois le même son et ensuite avec cette key de lecture je peux récupérer n'importe quel sons en lecture.

    Il est vrais que c'est sans doute un peu trop de contrôle à l'utilisateur mais vue que c'est sensé être un développeur et pas un utilisateur lambda j'ai souhaité lui donné un peu plus de contrôle.

    Mais je peux faire comme vous dites en retourner une key au moment ou j'add le son, toutes fois le nom du son suffirait.
    Et pareil au moment ou j'écoute un son la fonction d 'écoute renverrait une key de lecture.

    Je pense que le template va disparaître c'est certain.

    Sinon pour le problème qui m'avais fait posté même si je ne vois pas de solutions il n'a plus lieu d'être, au final c'était un problème de conception.
    Merci pour l'aide dans ma classe LittleWhite et merci au forum.

  10. #10
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2012
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Re bonjour,

    Je viens de m'apercevoir de quelque chose d'asse impressionnant en retirant les templates (ma connerie humaine).
    J'ai laisse les enums dans sur les int des keys et j'avais completement oublie qu'une enum passe dans un int sans probleme.
    Mon probleme de base n'avait vraiment pas mais alors VRAIMENT PAS lieu d'exister !!!!!!!!

    Voila bonne journee.

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Jeantorx Voir le message
    J'ai laisse les enums dans sur les int des keys et j'avais completement oublie qu'une enum passe dans un int sans probleme.
    Sauf que ton code a perdu un élément d'information. Un enum et un int, ce n'est pas la même chose quand on maintient un code. Dans le premier cas, on a un domaine de validité assez identifié (et même assez lisible si le nom des identifiants est bien choisi), dans le second on a un tout autre domaine. Est-ce que 42 est une valeur valide ? S'il s'agit d'un enum, à priori je sais que non, puisque je suis incité à utiliser les valeurs de ce type. S'il s'agit d'un entier, je suis obligé de deviner les hypothèses de l'auteur du code pour le savoir.

  12. #12
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2012
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Bonjour,

    Ok je vois le principe du domaine de validité, qui est plus qu'un principe même, J'ai un langage typé sous la main autant que je l'utilise correctement.

  13. #13
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Jeantorx Voir le message
    J'ai un langage typé sous la main autant que je l'utilise correctement.
    C'est exactement ça.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 22/11/2010, 14h15
  2. Fonction template dans une classe template
    Par mister3957 dans le forum Langage
    Réponses: 9
    Dernier message: 08/07/2008, 12h11
  3. Réponses: 8
    Dernier message: 20/07/2007, 14h28
  4. Class interne dans une classe template
    Par MatRem dans le forum Langage
    Réponses: 26
    Dernier message: 15/06/2006, 10h45
  5. Réponses: 4
    Dernier message: 08/11/2005, 15h10

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