delphi - class static method, static var in multi thread application - multithreading

I relative new with delphi XE2, I want to know about something, if I have like this code
TSomeClass=class
strict private
class var
FCounter:integer;
public
class procedure SomeProcedure();static
end;
implementation
class procedure SomeProcedure()
begin
inc(FCounter);
end;
initialization
begin
FCounter:=0;
end;
finalization
begin
FCounter:=0;
end;
As my understanding, SomeProcedure() will static on memory, and single instance,
my question
if TSomeClass accessed by many thread, TSomeClass thread-safe or not? or it will make overlapping between thread?
if yes, do I need critical section for each thread? or another approach for that kind of method...
if two different thread accessed this method, how about FCounter? FCounter will count sequential from last value or different thread with different value start from zero?

There is no synchronization between different invocations of methods. If the methods, no matter what type of methods they are, access shared data, then synchronization may be needed.
It does not make any difference if they method is a class method or an instance method, static or dynamic, etc. All that matters is whether or not there are shared objects being accessed from multiple threads.
If two different thread accessed this method, how about
FCounter? FCounter will count sequential from last value
or different thread with different value start from zero?
In your code, FCounter is a class variable. There is a single instance of the variable, shared between all threads. A class variable is just a global variable, nothing more, nothing less.
Your code modifies that shared variable. As written the code has a data race. You can solve it with synchronization. For example by using InterlockedIncrement rather than inc.
class procedure SomeProcedure;
begin
InterlockedIncrement(FCounter);
end;
For more complex objects you'd serialize with a critical section.

Your class is not thread safe.
The easiest way to get the counter thread safe is to use TInterlocked.Increment(FCounter) instead of Inc(FCounter). All TInterlocked methods are executed as atomic operations, the same applies for the Windows API function InterlockedIncrement() which could be used here as well.

Related

How Do I Call a Thread.Execute in GUI Thread?

There is a TThread descendant class with its own Execute method doing some math. It works fine but I am looking for the optimization of the following kind. The GUI thread and context of the program determine the count of necessary instances of these threads to be created, run and freed. In certain (rare or user determined) circumstances creation of one instance is enough.
By the moment I use the following construction (in pseudocode):
if ThreadsCount>1 then
begin
Creation of threads
starting them
waiting for results
evaluating and assigning the best result
freeing the threads
end
else
starting the math procedure (edited here separately)
// and in MyThread class declaration
procedure Execute... (edited here separately)
So there are two places in code that have my math procedure and I have to edit both of them if some math changes are applied. The GUI math procedure is a bit different from that one called in thread so I can not simply extract the method and call it.
I wonder if there is a way to create a thread instance and call its Execute method in GUI thread?
You could write some seriously hacky, indescribably bad code to enable you to safely call a TThread's Execute(). But it's an absurd thing to do. The whole point of the TThread class is that it:
starts a new thread in the OS;
then calls Execute() on that thread.
So:
If you don't need a thread, there's absolutely no point in starting a thread that you don't want to use.
You would need to prevent Execute() from doing any processing on its thread-run.
You could then call Execute from the main thread.
But since you have no guarantees how long the thread will take to not do any processing when it calls Execute(), you'd still need to wait for the thread to finish before you can destroy the TThread object.
The GUI math procedure is a bit different from that one called in thread so I can not simply extract the method and call it.
This makes absolutely no sense.
If your two "math procedures" are different, then trying to call the thread-implementation from GUI would change the behaviour of your program. Conversely, if you can reuse the thread-implementation, then you most certainly can also extract the method! (Or at the very least the common elements.)
Caution
That said, there is some caution required when sharing code that might run in a TThread.Execute(). Any code that must run on the main thread needs to be synchronised or queued. Inside TThread objects, you'd simply call the Synchronize() or Queue() method. However, shared code shouldn't be on a TThread object making things a little trickier.
To resolve this, you can use the the Synchronize() and Queue() class methods on TThread. This allows you to synchronise without instantiating a TThread instance. (Note these methods are safe to call from the main thread because they would simply call the sync method directly in that case.)
Code along the following lines should do the trick.
Implement your shared code in a suitable object. This is conceptually a runnable object, and something you may want to research.
TSharedProcess = class
private
{ Set this if the process is run from a child thread,
leave nil if run from main thread. }
FThread: TThread;
procedure SyncProc();
public
procedure Run();
property Thread: TThread read FThread write FThread;
end;
procedure TSharedProcess.Run();
begin
...
TThread.Synchronize(FThread, SyncProc);
...
end;
When you want to run the shared code from the main thread, the following is an option.
begin
LProc := TSharedProcess.Create(...);
try
LProc.Run();
finally
LProc.Free;
end;
end;
To run from a child thread a simple thread wrapper will suffice. And then you can create the runnable object in the main thread, and pass it to the thread wrapper.
{ TShardProcessThread for use when calling from child thread. }
constructor TSharedProcessThread.Create(AProc: TSharedProcessThread);
begin
FProc := AProc;
FProc.Thread := Self;
inherited;
end;
procedure TShardProcessThread.Execute();
begin
FProc.Run();
end;
{ Main thread creates child thread }
begin
{ Keep reference to FProc because it can only be destroyed after
thread terminates.
TIP: Safest would be to use a reference counted interface. }
FProc := TSharedProcess.Create(...);
try
LThread := TShardProcessThread.Create(FProc);
LThread.OnTerminate := HandleThreadTerminate;
except
{ Exception in thread create means thread will not run and
will not terminate; so free object immediately. }
FProc.Free;
raise;
end;
end;
Disclaimer
I have not tested this code because I see no benefit in doing something like this. Users gain nothing by being able to force code to run on the main thread. Furthermore the paradigms for synchronous code are fundamentally different to asynchronous code. Trying to implement a hybrid reduces maintainability by cluttering your 'business code' with technical detail.
Use at your own risk.
The way to approach this problem is to extract into a method the code that you need to perform either in a worker thread or the main thread. You can then call that code either from your worker thread's Execute method, or from your main thread code.

Synchronization from class Delphi

I have a question about multithreading in Delphi.
Suppose, I have a thread and I have a some class, that do some work and must have synchronization. How I can make it?
I make this procedure (In ThreadClass):
procedure TThreadClass.SynchProc(P: TProc);
begin
...
Synchronize(TThreadProcedure(P));
...
end;
And I call it from my class, that running in Thread, but ...
In procedure symbol "Synchonization" is a method of TThread, that is object "(Self as TThread)", but when I call it proc from my class, variable "Self" doesn't contain a my ThreadClass object (I dont know, that it's contained, may be object of second class, that running in Thread). respectively that procedure does not work.
I search oth variants (I'm passed my threadClass object to second class object and try to call "Synchronization" procedure from procedure of second class, but compiller did not want to compile it).
Can you help me? Will be grateful for any help
with greetings from Ukraine
PS Sorry for my bad English
I'm not 100% sure I understand, but I think you have a situation like this. You have a TThread descendent, say TMyThread. And that class in turn uses another class named TThreadClass which does not descend from TThread. You want to call Synchronize from a method of TThreadClass.
Here are some options:
Pass the TThread instance to TThreadClass. This is a rather brutal solution to the problem. Now TThreadClass can do anything to the thread when all it wants to do is call Synchronize.
Pass a procedural variable referring to the Synchronize method to TThreadClass. This gives TThreadClass the ability to do what it needs and no more.
Call the TThread.Synchronize class method passing nil for the first parameter.
Of these, the final option is the simplest. You can do it like this:
procedure TThreadClass.SynchProc(P: TThreadProcedure);
begin
TThread.Synchronize(nil, P);
end;
Note that it is not a good idea to pass in a TProc and cast to TThreadProcedure as per the code in the question. Force the caller to pass in a procedural variable of the right type. In this case the cast is benign, but you should always aim to avoid casts.

Delphi: preferred way of protection using Critical Sections

I have an object x that needs to be accessed from several (5+ threads). The structure of the object is
Tx = class
private
Fx: integer;
public
property x: integer read Fx read Fx;
etc;
What is the better (most elegant) way of protection:
a)
Tx = class
private
Fx: integer;
public
property x: integer read Fx read Fx;
public
constructor Create; <--- Create the criticalsection here
destructor Destroy; <--destroy it here
etc;
var
cs: TCriticalSection;
Obj: Tx;
function GetSafeObject(): Tx;
begin
CS.Enter;
try
Result:= Obj;
finally
CS.Leave;
end;
and access always the object as GetSafeObj().x:= 3;
or
Tx = class
private
Fx: integer;
FCS: TCriticalSection;
public
property x: integer read GerX read SetX;
public
constructor Create; <--- Create the criticalsection here
destructor Destroy; <--destroy it here
etc;
where
function Tx.Getx(): integer;
begin
CS.Enter;
try
Result:= Fx;
finally
CS.Leave;
end;
end;
end;
and always access the object normally. I guess the first option is more elegant, even if both methods should work fine. Ay comments?
Go for option B, making the critical section internal to the object. If the user of the class has to make use of an external function to safely access the instance, it is inevitable that somebody won't and the house will come tumbling down.
You also need to think about what operational semantic you are wanting to protect from multiple concurrent reads & writes. If you put a lock inside your getter and setter, you can guarantee that your object is internally coherent, but users of your object may see multithreading artifacts. For example, if thread A writes 10 to a property of your object, and thread B writes 50 to that property of the same object, only one of them can be last one in. If A happens to go first, then A will observe that they wrote a 10 to the property, but when they read it back again they see B's 50 that snuck in there in the gap between A's read-after-write.
Note also that you don't really need a lock to protect a single integer field. Aligned pointer sized integer writes are atomic operations on just about every hardware system today. You definitely need a lock to protect multi-piece data like structs or multi-step operations like changing two related fields at the same time.
If there is any way you can rework your design to make these objects local to a particular operation on a thread, do it. Making local copies of data may increase your memory footprint slightly, but it can dramatically simplify your code for multithreading and run faster than leaving mutex landmines all over the app. Look for other simplifying assumptions as well - if you can set up your system so that the object is immutable while its available to multiple threads, then the object doesn't need any lock protections at all. Read-only data is good for sharing across threads. Very very good.
Making the CS be a member of the object and using the CS inside of property getter/setter methods is the correct approach. The other approach does not work because it locks and unlocks the CS before the object is actually acessed, so the property value is not protected at all.
An easy way is to have a thread-safe wrapper around the object, similar to TThreadList. The wrapper needs two methods: Lock (to enter the critical section and return the inner object) and Unlock (to leave the critical section).

Class instances "owning" TMultiReadExclusiveWriteSynchronizer instances?

I have a multi-threaded Delphi program creating multiple instance of some classes, and I want each class instance to have its own instance of TMultiReadExclusiveWriteSynchronizer for use in the get and set methods of specific properties.
E.g. Here's part of a unit where I'm using a TMultiReadExclusiveWriteSynchronizer in one class:
interface
TSGThread=class(TThread)
private
fWaiting:boolean;
function getWaiting:boolean;
procedure setWaiting(value:boolean);
public
property waiting:boolean read getWaiting write setWaiting;
end;
implementation
var syncWaiting:TMultiReadExclusiveWriteSynchronizer;
function TSGThread.getWaiting:boolean;
begin
syncWaiting.BeginRead;
result:=fWaiting;
syncWaiting.EndRead;
end;
procedure TSGThread.setWaiting(value:boolean);
begin
syncWaiting.BeginWrite;
fWaiting:=value;
syncWaiting.EndWrite;
end;
initialization
syncWaiting:=TMultiReadExclusiveWriteSynchronizer.Create;
finalization
syncWaiting.Free;
end.
The problem with this is that the unit creates one instance of TMultiReadExclusiveWriteSynchronizer which is then used by multiple instances of TSGThread.
The synchronizer is only controlling access to a private field of TSGThread.
Thread A could modify the field in Thread B using the public property, hence the need for the synchronizer, but there should be a separate synchronizer in each thread so the threads don't have to wait on each other if they're modifying their own properties.
Delphi Help says "create a global instance of TMultiReadExclusiveWriteSynchronizer", but is it strictly necessary for it to always be global?
If a class is only protecting access to its own properties, will the synchronization work with a TMultiReadExclusiveWriteSynchronizer instance in a private field?
The help says this:
Create a global instance of TMultiReadExclusiveWriteSynchronizer that is associated with the global memory you want to protect.
But you don't have global memory. You have thread-object-specific memory, so create synchronization objects for each thread object. You can create as many as you need. Create one for each shared element you wish to individually access and protect.
This is a little bit off-topic, but in the example you give, the synchronizer is pretty much useless. A boolean cannot be partially read/written on a thread context switch.
Also, with your example, code like this
sgThread.Waiting := not sgThread.Waiting;
could fail.
Now, back to the topic. TMultiReadExclusiveWriteSynchronizer's scope needs to be as large as the resource it protects. Since you want to protect a private field of an object, you can declare the TMultiReadExclusiveWriteSynchronizer as a private field as well. (You are protecting access to the private field, not the access to the property)
It's not strictly necessary for it to be global. It is necessary for the every access to go through the synchronizer in order to maintain thread safety. One easy way to enable that is by making the synchronizer a global variable, but there are other ways to handle it.

Accessing Variable in Parent Form from OnTimer Event - Getting Exception

I'm getting an exception in an OnTimer event handler (TTimer) that when executed increments an integer variable in the parent form. The timers need to be able to access an incremented integer used as an id.
My first question is: How can I tell in Delphi 2007 which code is running in which thread? Is there a way in debug mode to inspect this so I can determine for sure?
Secondly, if I need to access and modify variables in a parent form from another thread, what is the best way to do that? It seems like sometimes Delphi allows me to access these variables "incorrectly" without giving an exception and other times it does give an exception.
Just to be sure: On one hand you are talking about a timer event, on the other about multithreading. Those are two totally different ways of running code in parallel.
A timer will always be run in the main thread. It should be safe there to access everything that was created and is being used in the main thread. In fact, a timer event can only occur, when no other main thread code is running, because it needs the application's message handler to process the timer message. So it is either outside of any event handling code or when one of your event handlers calls Application.ProcessMessages.
A thread is very different from this. In this case, the code in different threads runs independently from each other. If running on a multi-processor machine (or multi core), it is even possible they truly run in parallel. There are quite a few issues you may have this way, in particular the Delphi VCL (up and including Delphi XE) is not thread save, so calls to any VCL class must only be done from the main thread (there are a few exceptions to this rule).
So, please first clarify whether you are talking about timers or true multithreading, before expecting any useful answers.
How can I tell in Delphi 2007 which
code is running in which thread? Is
there a way in debug mode to inspect
this so I can determine for sure?
You can set a breakpoint and when execution stops look at the threads debug window. Double click on each thread to see its callstack in the callstack debug window. You can also use the Win32 function GetCurrentThreadId to find out about the current thread (e.g. for logging, or to determine if the current thread is the main thread etc).
Since you are not showing any code it is hard to be more specific. Just to be sure: code in a timer event handler is not getting executed in a different thread. You won't have concurrent-access issues if you are just using timers, not real background threads.
Secondly, if I need to access and
modify variables in a parent form from
another thread, what is the best way
to do that? It seems like sometimes
Delphi allows me to access these
variables "incorrectly" without giving
an exception and other times it does
give an exception.
If you really are in another thread and access a shared variable you can see all sorts of things happening if you don't protect that access. It might work ok most of the time or you get strange values. If you just want to modify an integer in a thread-safe manner, look at InterlockedIncrement. Otherwise you could use a critical section, mutex, monitor... JEDI has some useful classes in the JclSynch unit for that.
You are asking two questions, so I'll answer them in two answers.
Your first question is about using TTimers; those always run in the main thread.
Most likely, your exception is an access violation.
If it is, it is usually caused by either of these:
a- your parent form is already
destroyed when your TTimer fires.
b- your do not have a reference yet to
your parent form when your TTimer
fires.
b is easy: just check if your reference is nil.
a is more difficult and depends on how you reference your parent form.
Basically you want to make sure your reference gets nil when the parent is being destroyed or removed.
If you reference your parent form through a global variable (in this example through Form2), then you should have TForm2 make the Form2 variable nil using the OnDestroy event like this:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm2 = class(TForm)
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.FormDestroy(Sender: TObject);
begin
Form2 := nil;
end;
end.
If you are using a field reference to your parent form (like FMyForm2Reference), then you should use add a Notification method like this:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Unit2;
type
TForm1 = class(TForm)
private
FMyForm2Reference: TForm2;
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) then
if (AComponent = FMyForm2Reference) then
FMyForm2Reference := nil;
end;
end.
Regards,
Jeroen Pluimers
You are asking two questions, so I'll answer them in two answers.
Your second question is about making sure only 1 thread accessing 1 variable in a form at a time.
Since the variable is on a form, the best way is to use the Synchronize method for this.
There is an excellent example about this which that ships with Delphi, it is in the thrddemo.dpr project, where the unit in SortThds.pas has this method that shows how to use it:
procedure TSortThread.VisualSwap(A, B, I, J: Integer);
begin
FA := A;
FB := B;
FI := I;
FJ := J;
Synchronize(DoVisualSwap);
end;
Good luck,
Jeroen Pluimers

Resources