Hm, ich lasse mich gerne vom Gegenteil überzeugen und mir ein einfacheres Konzept unterbreiten
Hier das
Problem, welche ich erschlagen muss:
Ich habe einen LogController, der als Singleton-Pattern angelegt ist, d.h. ich hole mit die Instanz via einer statischen Klassenmethode
TLogController.GetInstance()
. Ich logge ebenso über eine statische Klassenmethode
TLogController.Log( {Parameter} );
, die intern die GetInstance()-Methode verwendet.
Es gibt die Möglichkeit bei dem LogController EventListener zu registrieren, d.h. ich übergebe einen Zeiger auf eine Methode, die dann gecalled wird. Ebenso kann ich auch Module registrieren, die mehr Funktionalitäten bieten -- diese Module implementieren meinem Interface
ILogModule. Ein Module ist im Moment z.B. das FileLogModule, welches, wie der Name schon sagt, die eintreffenden Logs in bestimmte Dateien schreibt.
Ganz wichtig ist, dass dieser LogController von mehreren Threads parallel benutzt werden kann und somit threadsicher sein muss. Ich habe in letzter Zeit schon mehrere Threads (hier im Forum
) geschrieben, die mir Lösungen zu diesem Problem geben sollten. So recht gefällt mir das mit diesem globalen Thread ja auch nicht. Jedenfalls habe ich im Moment nun folgendes Konzept: Die statische Klassenmethode
Log() ist mit CriticalSections geschützt. Intern werden verschiedene Queues gefüllt -- für alle EventListener eine und für jedes Module separat eine. Danach wird die Nachricht WM_LOG_NOTIFIER (selbst definiert) via PostThreadMessage an den MainThread geschickt. Nun will ich ja, dass ich für den LogController keinerlei weiteren Code in das eigentliche Programm schreiben muss, da dies sonst Probleme beim Ändern oder Entfernen des LogControllers geben kann. Daher will ich in den MainThread auch nicht die passende Weiterleitung der Nachricht implementieren und mir bleibt nur der Weg über den globalen Hook.
Warum aber diese Nachricht? Das hat den Hintergrund, dass die EventListener und Module synchronisert benachrichtigt werden sollen (ohne Messages, da ich das bisherige Konzept beibehalten will), da teilweise auf die
VCL zugegriffen werden kann. Die Message an den MainThread sorgt dafür, dass der Code für die Benachrichtigung auf unter dessen Kontext statt findet. Nachdem der MainThread ja unter Umständen auch mal blockiert sein kann (durch die CriticalSection in der Log()-Methode) ist eine Nachricht eben das/ein passende Mittel, um einen Deadlock zu umgehen -- weitere kenne ich im Moment leider nicht.
Ich habe im Moment aber auch noch die folgende Idee: Die Log-Methode wird komplett umgebaut, sodass darin in etwa folgendes steht (frei runtergeschrieben):
Delphi-Quellcode:
class procedure TLogController.Log(const AMessage: String; const ALogType: TLogType);
begin
TThread.Synchronize(
nil
procedure()
var
LR : PLogRecord;
begin
New(LR);
LR^.Text := AMessage;
LR^.MsgType := ALogType;
PostMessage(TLogController.Handle, WM_LOG_NOTIFIER, Integer(LR), 0);
end
);
end;
Die Idee hierbei ist es, dass ich dem TLogController ein
Handle zur hand gebe und die Benachrichigung syncronisiert da hin schicke. Ich weiß nur leider nicht, ob das möglich ist, da ic das nur konzeptionell in meinem Kopf habe
Wenn jemand aber
die super Idee hat, dann teile er sie mir doch bite mit
Herzlichsten Dank!
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)