Ich habe eine einfache Protokollierungsklasse erstellt und möchte bestätigen, dass sie Thread-sicher ist. Grundsätzlich werden die Log
, RegisterLogger
und UnRegisterLogger
aus verschiedenen Threads aufgerufen. Log
wird viel (von vielen verschiedenen Threads) und RegisterLogger
und UnRegisterLogger
selten genannt werden.In Delphi sind auf TList <x> Thread sicher gelesen?
Grundsätzlich kann meine Frage auf den Punkt gebracht werden: "Sind auf TList<x>
thread sicher gelesen?", Das heißt, kann ich mehrere Threads Zugriff auf eine TList
zur gleichen Zeit haben.
IExecutionCounterLogger
ist eine Schnittstelle mit einem Log-Methode (mit derselben Signatur wie TExecutionCounterServer.Log
)
Type
TExecutionCounterServer = class
private
Loggers : TList<IExecutionCounterLogger>;
Synchronizer : TMultiReadExclusiveWriteSynchronizer;
public
procedure RegisterLogger(Logger : IExecutionCounterLogger);
procedure UnRegisterLogger(Logger : IExecutionCounterLogger);
procedure Log(const ClassName, MethodName : string; ExecutionTime_ms : integer);
constructor Create;
destructor Destroy; override;
end;
constructor TExecutionCounterServer.Create;
begin
Loggers := TList<IExecutionCounterLogger>.Create;
Synchronizer := TMultiReadExclusiveWriteSynchronizer.Create;
end;
destructor TExecutionCounterServer.Destroy;
begin
Loggers.Free;
Synchronizer.Free;
inherited;
end;
procedure TExecutionCounterServer.Log(const ClassName, MethodName: string; ExecutionTime_ms: integer);
var
Logger: IExecutionCounterLogger;
begin
Synchronizer.BeginRead;
try
for Logger in Loggers do
Logger.Log(ClassName, MethodName, ExecutionTime_ms);
finally
Synchronizer.EndRead;
end;
end;
procedure TExecutionCounterServer.RegisterLogger(Logger: IExecutionCounterLogger);
begin
Synchronizer.BeginWrite;
try
Loggers.Add(Logger);
finally
Synchronizer.EndWrite;
end;
end;
procedure TExecutionCounterServer.UnRegisterLogger(Logger: IExecutionCounterLogger);
var
i : integer;
begin
Synchronizer.BeginWrite;
try
i := Loggers.IndexOf(Logger);
if i = -1 then
raise Exception.Create('Logger not present');
Loggers.Delete(i);
finally
Synchronizer.EndWrite;
end;
end;
Als wenig Hintergrund, das ein aus this question folgen eingeschaltet ist. Im Grunde habe ich zu jeder Methode eines (DCOM) DataSnap-Servers eine Instrumentierung hinzugefügt, außerdem bin ich in jedes TDataSnapProvider OnGetData und OnUpdateData-Ereignis eingebunden.
Der Synchronisierer ist TMultiReadExclusiveWriteSynchronizer –
Vielleicht habe ich die Frage nicht richtig. Die Verwendung des Synchronizers ist offensichtlich threadsicher (das ist der ganze Zweck). Ich verstand Alister, dass er es für den Leseteil weglassen wollte. –
Nein, Alister fragt, ob TList Reads ordnungsgemäß funktionieren, wenn mehrere "Reader" gleichzeitig ausgeführt werden. –
gabr