Bonjour,

J'ai un petit probl�me d'utilisation des smart pointers de boost, notamment shared_ptr et weak_ptr. Je pr�cise que c'est ma premi�re "vraie" utilisation des smarts pointers (mes exp�riences pr�c�dentes se limitaient � des tests pour voir un peu comment �a marchait).

J'essaie de construire une architecture de type DEM (delegate event model), avec quelque chose de tr�s basique pour commencer. Un peu du style :
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
class Listener
{
public:
    virtual ~Listener() {}
    virtual void onEvent() = 0;
};
 
class Source
{
public:
    virtual ~Source() {}
    void addListener(Listener*);
    void removeListener(Listener*);
 
private:
    list<Listener*> listeners_;
};
Un Listener peut s'enregistrer aupr�s d'une Source en appelant addListener() sur celle-ci, et se d�senregistrer par removeListener(). La source peut ensuite notifier ses listeners_ quand bon lui semble en appelant leur m�thode onEvent(). J'omets volontairement toute notion de type d'�v�nement, identit� de la source, etc...

Mon probl�me concerne le fait que lorsqu'un Listener est d�truit, il faut bien qu'il soit retir� des listeners_ des diff�rentes Sources aupr�s desquelles il s'est enregistr�. On pourrait penser � un syst�me plus complexe o� les Sources �coutent elles-m�mes des �v�nement du genre DeletionEvent envoy�s par leur listeners, mais c'est tordu. Un coll�gue m'a expliqu� qu'en Java ce m�canisme s'obtient typiquement � base de weak references. Je me suis donc dit qu'il suffisait d'utiliser des shared_ptr dans mon programme, et de les passer aux Sources au lieu des pointeurs natifs, pour qu'elles puissent en faire des weak_ptr, afin de pouvoir les virer quand leur expired() retourne false (il me semble que c'est comme �a qu'on utilise les weak_ptr, dites-moi si je me trompe).

Du coup la d�claration devient :
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
 
class Source
{
public:
    virtual ~Source() {}
    void addListener(shared_ptr<Listener>);
    void removeListener(shared_ptr<Listener>);
 
private:
    list<weak_ptr<Listener> > listeners_;
};
Et la m�thode addListener() ressemblerait en gros � ceci :
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
 
void Source::addListener(shared_ptr<Listener> listener)
{
    listeners_.push_back(weak_ptr<Listener>(listener));
}
Et la m�thode qui notifie les listeners_ en les parcourant se chargerait de tester leur expired() et de les supprimer si besoin.

Sa me semble tenir la route. Seulement voil� mon probl�me : autant le fait d'attacher un listener � une source sera tr�s facile pour un code client qui fait tout par shared_ptr, et aura donc juste � passer ses shared_ptr de listeners � ses sources, autant c'est beaucoup plus difficile si on veut qu'un listener puisse s'enregistrer tout seul. Vu que quand on est dans le code du listener lui-m�me, on ne peut bien s�r pas faire :
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
 
source.addListener(this); // ne compile pas
et encore moins :
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
 
source.addListener(shared_ptr<Listener>(this)); // provoque une catastrophe : this sera détuit à la fin de l'instruction
Du coup je me retrouve avec des belles id�es mais qui sont finalement assez inutile puisqu'il est quand m�me plus que fr�quent dans ce type d'architecture qu'une classe d�rivant de Listener d�cide d'elle-m�me d'�couter une source ! (c'est presque le cas nominal...).

Que pensez-vous de ce probl�me ? Avez-vous d�j� �t� confront� � ce genre de chose ? Je ne suis un habitu� ni des smart pointers ni des event models, donc j'avoue �tre un peu d�sempar�. J'ai beau �tre fan de C++, l� je dois avouer que �a serait un jeu d'enfant en Java....

Toute id�e sera appr�ci�e.

Merci d'avance