Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

[C++] Singleton en callbacks

Pagina: 1
Acties:

  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 14-11 00:35
Ik heb een programma gemaakt maar nu moet er iets tegevoegd wordt: 'events'. Nu is dat niet zo een probleem en zou ik het doen dmv callbacks. Het enigste probleem is het aspect templates + singletons.

Mijn programma bestaat uit een gui (CDialog) en meerdere singletons.
Zo'n singleton:
C++:
1
2
3
4
5
6
7
template< class C >
class Singleton
{
public:
    static C& Current();
//etc...
}


Een interface hiervoor
C++:
1
2
3
4
5
6
template< class resource >
class Resource : public Singleton<resource>
{
protected:
    static void DisplayOnReceive();
}


en een implementatie:
C++:
1
2
3
4
5
6
7
8
class AResource : public Resource<AResource>
{
static int32_t OnReceive(bladiebla)
{
    DisplayOnReceive();
    //bladiebla
}
}


Nu is het probleem dat ik gebruik maak van een 3rd suplier C library, deze heeft static callbacks naar OnReceive. Nu wil ik van OnReceive een notificatie sturen naar mijn GUI class.

Hoe ik dit wilde realiseren is bij de Resource een pointer naar mijn CDialog gui achterlaten en die aanroepen bij DisplayOnReceive.

Wat ik wilde is bij de Resource class een private member CDialog hebben, een functie RegisterCallback(CDialog* dialog) die de member zet. bij DisplayOnReceive deze member aanspreken, maar dit gaat niet omdat de functie DisplayOnReceive een static is. Ik kan ook niet Resource::Current() doen omdat ik specifieke resources implementaties heb.

Mijn vermoeden is dat ik het ook de na call van DisplayOnRecieve in AResource, BResource de member kan aanspreken via AResource::Current().m_Callback->UpdateComboBox();

Dus dat de registratie in Resource staat:
C++:
1
2
3
4
5
6
7
8
9
10
template< class resource >
class Resource : public Singleton<resource>
{
public:
    void registerCallback(Cdialog* dialog) {m_Callback = dialog);
protected:
    static void DisplayOnReceive();

    CDialog* m_Callback;
}


En de implementatie in AResource
C++:
1
2
3
4
5
6
7
8
class AResource : public Resource<AResource>
{
static int32_t OnReceive(bladiebla)
{
    DisplayOnReceive();
    AResource::Current().m_Callback->UpdateComboBox();
}
}


Kan ik op 1 of andere manier er voor zorgen dat de aanroep van UpdateCombox maar 1 keer hoef te typen in de classe Resource, functie DisplayOnReceive dat ik bij elke andere Resource daar niet meer op hoef te letten :?

/laptekst

[This space is for rent]


  • Dricus
  • Registratie: Februari 2002
  • Laatst online: 12:58

Dricus

ils sont fous, ces tweakers

Hmm, het vervelende hieraan is dat je vanuit je AResource class direct een call doet op je CDialog class. Zoals ik het denk te begrijpen is het de bedoeling dat er aan de hand van dingen die kunnen gebeuren in je AResource class zaken in je UI aangepast moeten worden.

Ik probeer UI code altijd strict gescheiden te houden van code in non-UI-classes. Mijn oplossing zou in dit geval zijn om je AResource class een HWND van je window door te geven waar hij dan met behulp van PostMessage een event heen kan sturen. Je CDialog class kan aan de hand van dat event vervolgens zijn eigen UpdateComboBox aanroepen. Deze aanpak heeft minstens 2 voordelen (er zijn er nog wel meer te bedenken):
  1. Je CDialog class is gemakkelijk aan te passen zonder dat dit gevolgen heeft voor je AResource class. Stel dat je besluit om ipv een ComboBox een ListBox te gaan updaten, dan hoef je daar je AResource class niet voor te wijzigen.
  2. Het is asynchroon. Hierdoor is het mogelijk dat je AResource dingetjes in een andere thread gebeuren dan je CDialog dingetjes.

Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...


  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 14-11 00:35
MrHuge schreef op woensdag 29 oktober 2008 @ 11:26:
Hmm, het vervelende hieraan is dat je vanuit je AResource class direct een call doet op je CDialog class. Zoals ik het denk te begrijpen is het de bedoeling dat er aan de hand van dingen die kunnen gebeuren in je AResource class zaken in je UI aangepast moeten worden.

Ik probeer UI code altijd strict gescheiden te houden van code in non-UI-classes. Mijn oplossing zou in dit geval zijn om je AResource class een HWND van je window door te geven waar hij dan met behulp van PostMessage een event heen kan sturen. Je CDialog class kan aan de hand van dat event vervolgens zijn eigen UpdateComboBox aanroepen. Deze aanpak heeft minstens 2 voordelen (er zijn er nog wel meer te bedenken):
  1. Je CDialog class is gemakkelijk aan te passen zonder dat dit gevolgen heeft voor je AResource class. Stel dat je besluit om ipv een ComboBox een ListBox te gaan updaten, dan hoef je daar je AResource class niet voor te wijzigen.
  2. Het is asynchroon. Hierdoor is het mogelijk dat je AResource dingetjes in een andere thread gebeuren dan je CDialog dingetjes.
De implementatie dus in de de AResource/BResources dus. In CDialog een extra regel toevoegen in de Message_map bij dat bericht?

[This space is for rent]


  • Dricus
  • Registratie: Februari 2002
  • Laatst online: 12:58

Dricus

ils sont fous, ces tweakers

PoweRoy schreef op woensdag 29 oktober 2008 @ 11:42:
De implementatie dus in de de AResource/BResources dus. In CDialog een extra regel toevoegen in de Message_map bij dat bericht?
Over welke implementatie heb je het hier? Ik bedoel te zeggen dat de implementatie van het updaten van je UI in je CDialog class zit. En dat je AResource class niets meer doet dan een event sturen naar je window. Je CDialog class kan dat event afvangen (kun je met je message map doen idd) en in de event handler de UI updaten.

Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...


  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 14-11 00:35
MrHuge schreef op woensdag 29 oktober 2008 @ 11:53:
[...]

Over welke implementatie heb je het hier? Ik bedoel te zeggen dat de implementatie van het updaten van je UI in je CDialog class zit. En dat je AResource class niets meer doet dan een event sturen naar je window. Je CDialog class kan dat event afvangen (kun je met je message map doen idd) en in de event handler de UI updaten.
Ik bedoelde de PostMessage versturen vanuit AResource en niet vanuit Resource. Waardoor ik bij elke implementatie van Resource deze postmessage moet doen. (Ipv 1 keer bij de template Resource

[This space is for rent]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:54
Ff kijken of ik het begrijp:

- 3rd party lib doet een callback naar een static functie.
- Op deze callback wil je meerdere objecten laten reageren met bepaalde acties.

Maw je hebt een controller nodig waarbij je listeners kunt registreren; deze controller registreert zijn eigen static callback bij de library.

Aangezien de callback static is zul je ook de lijst met listeners static moeten maken, echter een static variabele in Resource< A > en Resource< B > zullen niet dezelfde variabele zullen zijn, het zijn immers andere typen.

Als je zoiets zou willen zou je een derde object dit werkt moeten laten doen, waarbij zowel je listeners als je Resource< A > en Resource< B > bij kunnen.

Overigens zoals eerder aangegeven zou ik niet het type van de listener een CDialog maken, maar een op zijn minst een HWND, maar liever nog een compleet UI ungerelateerde interface.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Dricus
  • Registratie: Februari 2002
  • Laatst online: 12:58

Dricus

ils sont fous, ces tweakers

PoweRoy schreef op woensdag 29 oktober 2008 @ 12:08:
Ik bedoelde de PostMessage versturen vanuit AResource en niet vanuit Resource. Waardoor ik bij elke implementatie van Resource deze postmessage moet doen. (Ipv 1 keer bij de template Resource
Ah, my bad, ik zou het dan inderdaad ook in Resource doen. Zoals hierboven aangegeven zou het nog wat mooier zijn om een compleet niet-UI-gerelateerd callback mechanisme te hebben. Je zou hiervoor eens naar het Observer Pattern kunnen kijken.

Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...

Pagina: 1