I have a TThread object named TTestThread. When the threads are created, they make a local copy of the global configuration variables. The user is allowed to change the global configuration variables at any time, and when he does so, all threads are notified of the change via their local UpdateLocalCopyOfConfigVariables variable. The threads don't rely on the global configuration variables directly because they can be modified at any point by the user, which would create a race condition if the threads were to access them at the same time.
Here's TTestThread:
type
TTestThread = class(TThread)
private
LocalConfigA : String;
LocalConfigB : Integer;
procedure UpdateLocalConfigIfNecessary;
protected
procedure Execute; override;
public
UpdateLocalCopyOfConfigVariables : Boolean;
constructor Create;
end;
implementation
constructor TTestThread.Create;
begin
inherited Create(false);
UpdateLocalCopyOfConfigVariables := true;
end;
procedure TTestThread.UpdateLocalConfigIfNecessary;
begin
WaitForSingleObject(ConfigurationLocker, INFINITE);
if (UpdateLocalCopyOfConfigVariables) then
begin
LocalConfigA := GlobalConfigA;
LocalConfigB := GlobalConfigB;
UpdateLocalCopyOfConfigVariables := false;
end;
ReleaseMutex(ConfigurationLocker);
end;
procedure TTestThread.Execute;
begin
while (not(Terminated)) do
begin
UpdateLocalConfigIfNecessary;
// Do stuff
end;
end;
As you can see, I have a mutex in place to avoid the sort of race condition described earlier. WaitForSingleObject(ConfigurationLocker, INFINITE); is called when the user changes the global configuration variables:
procedure ChangeGlobalConfigVariables(const NewGlobalConfigA : String ; NewGlobalConfigB : Integer);
var
I : Integer;
begin
WaitForSingleObject(ConfigurationLocker, INFINITE);
GlobalConfigA := NewGlobalConfigA;
GlobalConfigB := NewGlobalConfigB;
for I := 0 to ThreadList.Count - 1 do
TTestThread(ThreadList[I]).UpdateLocalCopyOfConfigVariables := true;
ReleaseMutex(ConfigurationLocker);
end;
The thing is, while it prevents the threads from updating their local copy of configuration variables at the same time the global configuration variables are being changed, it also prevents two threads from updating their local configuration at the same time – even if the global configuration variables are not being changed. As far as I know, race condition is an issue when there's writing going on. If the global configuration variables are the same, then the threads can all update their local copy at the same time with no issues.
Am I right? If so, is there a way to fix this issue? Granted, it's not a big one, but I still feel like there has to be a better solution...
It seems a good point for TMultiReadExclusiveWriteSynchronizer work