Generic intrinsic wrapper
Threads. Love’em or hate’em, but sometimes exposing properties between your main Delphi application and your threads can be tricky. There are rules to accessing memory such as “several processes may read from the same memory, but you can never read and write at the same time”. If you get it wrong, you’ll produce a spectacular access violation.
So how do you safely expose properties in your TThread descendants which both the thread and your main VCL application can access? Well take your pick, from a mutex, a semaphore, synchronization calls all the way to brute-force TCriticalSection. You can even cleverly sculpt your properties read / write access so that data can be safely shared. But that is probably more painful than fun.
Keep it simple
My take on the problem is somewhat ad-hoc, depending on the situation and application of course. But a neat trick is to wrap intrinsic datatypes in bridge classes. Now before you state the obvious “hey, that’s what COM variants do!” — remember that Delphi now targets quite a number of platforms, so making stuff “all delphi” has it’s benefits.
And with generic’s it’s not much code either:
TLockedValue<T> = Class(TObject) private FLock: TMultiReadExclusiveWriteSynchronizer; FData: T; protected function GetValue:T; procedure SetValue(Value: T); public Property Value:T read getValue write setValue; Constructor Create;virtual; Destructor Destroy;override; end; Constructor TLockedValue.Create; begin inherited; FLock := TMultiReadExclusiveWriteSynchronizer.Create; end; Destructor TLockedValue.Destroy; begin FLock.Free; inherited; end; function TLockedValue.GetValue:T; begin FLock.BeginRead; try result:=FData; finally FLock.EndRead; end; end; procedure TLockedValue.SetValue(Value: T); begin FLock.BeginWrite; try FData:=Value; finally FLock.EndWrite; end; end;
Well, the use should be pretty obvious. And it makes even more sense the other way around – when threads want to write values back into the main VCL process. It’s also very handy for state flags which can be altered by multiple running threads (like counters) and so on…