"Riverwind" <riverwind@heaven.dk> wrote
[snip]
> Det er mig bekendt fatalt at kalde virtuelle metoder, efter at
> destructoren er blevet kaldt.
Absolut ja.
> Jeg har prøvet at løse det ved at overskrive operator delete for min
> basethread, men det kunne ikke kompilere.
Det ville også kun virke for heap-allokerede objekter.
> Jeg vil helst undgå at skulle sætte variablen i de nedarvede klasser,
> ligesom jeg vil undgå at skulle sætte den, der hvor tråd-objekterne er
> instantieret.
Det kan jeg godt forstå.
Det er et alvorligt problem, med en interessant løsning:
I stedet for at applikationsklassen arver fra MessageThread, så arver
MessageThread fra applikationsklassen.
Det er givetvis overraskende, hvis du ikke har set det før, men tænk
grundigt over det.
> Nogen gode råd til hvordan jeg kan sætte variablen inden destructoren
> går igang?
Det er ikke vigtigt at variablen sættes _før_ destructoren påbegyndes.
Det er derimod vigtigt at den virtuelle metode ikke kaldes _efter_
destructoren er færdig.
Jeg antager at destructoren kaldes fra en anden tråd end sig selv.
Den rene løsning er derfor at klassen f.eks. har et event objekt (oprettet
med Win32 API funktionen "CreateEvent"). I destructoren skal flaget sættes,
og derefter ventes der på at der bliver signaleret på eventen. I tråden
tester man på flaget, og afslutter når message-loop'et og signalerer på
eventen.
(Ikke testet skitse: jeg har ikke tid til alle detajlerne lige nu, men
syntes det er vigtigt nok til at give et ufuldstændigt svar)
template <typename T>
class MessageThread : public T
{
public:
~MessageThread();
// Note no virtual MessageHandler !!!
private:
HANDLE m_TerminateEvent;
};
MessageThread:
MessageThread()
{
m_bTerminate = TRUE; // Win32 BOOL type ?!?
// Wait for thread to terminate
WaitForSingleObject(m_TerminateEvent, INFINITE);
}
void Message::Thread::MessageLoop()
{
while(!m_bTerminate) {
// ...
// MessageHandler();
}
SetEvent(m_TerminateEvent);
}
class MyHandler
{
public:
// Note MessageHandler is _not_ virtual
void MessageHandler();
};
int main()
{
MessageThread<MyHandler> mh;
}
Venlig hilsen
Mogens Hansen