Accessing the same object from concurrent threads - multithreading

Have two object instance that i should access from two concurrent thread, from the VCL thread and from a worker thread.
TSlave = class
...
public
...
statusByte: byte;
...
end;
TMaster = class
private
FSlaves: TList;
FrBuffer: array of byte;
...
public
CMD_GET_SLAVE( aSlave: TSlave );
...
end;
procedure TMaster.CMD_GET_SLAVE( aSlave: TSlave );
begin
...
rBuffer := udpsend(); //calling a function that sends udp packet and returns the answer
aSlave.statusByte := rBuffer[2];
...
end;
I store the references of the slave objects in the 'Data' fields of VCL TTreeNodes - treenode.data (i store them also in a TMaster private list).
There are two 'option' for accessing the slave object (writing slave.statusByte) and the TMaster instance (as i access the slave object through a TMaster instance) >>
Clicking on the treenode. When this happens i send an UDP packet with calling master.CMD_GET_SLAVE, in this method i read the answer from FrBuffer and writing slave.statusByte.
There is a worker thread that is cyclically doing the same (calling master.CMD_GET_SLAVE). This case i dont get the slave instances from treenode.data, but from the master's TList object (FSlaves).
The question is, how to manage this correctly? Because there is a possible situation when the user clicks on the treenode and in the same time there could be an incoming access from the thread.
I dont touch any VCL control from the worker thread, 'just' accessing the same objects from two concurrent thread. Should i just do the same synchronization that im doing when synchronizing the main VCL thread (because of refreshing some visual VCL control)?

If you have multiple threads that access access a shared object, and at least one thread modifies the object, then you usually need to use a lock (for instance TCriticalSection or TMonitor) to serialize access to the shared object. Some options for doing so:
Externally protect all access to the shared object with the lock.
Make the object self synchronizing using its own private lock. That is the internally synchronized option.
Option 2 is simpler for the caller, but forces all consumers of the class to pay the cost of synchronization. A an alternative is to make the object have no internal synchronization but then wrap a synchronization class around it that presents a thread-safe version.

In this particular example, accessing the slaves across multiple threads is not a problem. The real problem is udpsend(). You are running the risk of having two threads sending requests at the same time and then reading each other's responses. Depending on the nature of your UDP protocol, that may or may not cause problems.
If it does, you might need to move the UDP communications to its own dedicated thread. When you need to send a request, you could put it in a thread-safe queue that the thread looks at, along with info about what to do with the response when it arrives (assign it to a slave, call a callback function, signal a waitable event, etc). The thread can pick up a queued request and send it. When the response comes back, it can delegate it accordingly. CMD_GET_SLAVE() would then block its calling thread waiting for that response to arrive. This would help avoid any overlaps.

Related

How to automatically initialize / uninitialize something globally for every thread?

I have a unit with an initialization and finalization section. This unit contains a complex object which is instantiated in the initialization and destroyed in the finalization. However, this object also contains an ADO Connection. That makes it an issue when using this across threads, because ADO is COM, and needs to be initialized for every thread.
This is how I currently handle this global object instance:
uses
ActiveX;
...
initialization
CoInitialize(nil);
_MyObject:= TMyObject.Create;
finalization
_MyObject.Free;
CoUninitialize;
end.
This only works on the main thread. Any other thread wouldn't be able to access it, and will return an exception CoInitialize has not been called.
How do I get around this to make this unit thread-safe? I would need a way to hook every creation/destruction of any thread created, and each thread would need to refer to a different instance of this object. But how to go about doing so?
Well, as you already say yourself, each thread needs to call CoInitialize separately. And in addition, each thread needs to have its own ADOConnection too.
I think you need to leave the idea of using the single global object/connection from that unit. Just repeat that object creation and destruction in each thread. When the thread types are different, then you could design a base thread class on top of them. If the object is too big (has overhead with regard to the thread) or does not 'fit' completely in the thread, then split the object design.
For now, your question sounds like just wanting to keep convenience, but if it is really necessary to centralize the ADO connection involvement, then maybe you could implement multi-cast events for the connection events of both main thread and the other threads. Logging in should not be a problem for successive connections: just store the login values and feed them to the threads.
While another design might be a better solution, you can declare _MyObject as threadvar to have a separate instance for each thread. In addition you can move the CoInitialize/CoUnitialize into the constructor/destructor of TMyObject.
I cannot give advice on when to create and free these instances as I have no idea how your threads are created and freed.

How to do asynchronuous programming in Delphi?

I have an application, where most of the actions take some time and I want to keep the GUI responsive at all times. The basic pattern of any action triggered by the user is as follows:
prepare the action (in the main thread)
execute the action (in a background thread while keeping the gui responsive)
display the results (in the main thread)
I tried several things to accomplish this but all of them are causing problems in the long run (seemingly random access violations in certain situations).
Prepare the action, then invoke a background thread and at the end of the background thread, use Synchronize to call an OnFinish event in the main thread.
Prepare the action, then invoke a background thread and at the end of the background thread, use PostMessage to inform the GUI thread that the results are ready.
Prepare the action, then invoke a background thread, then busy-wait (while calling Application.ProcessMessages) until the background thread is finished, then proceed with displaying the results.
I cannot come up with another alternative and none of this worked perfectly for me. What is the preferred way to do this?
1) Is the 'Orignal Delphi' way, forces the background thread to wait until the synchronized method has been executed and exposes the system to more deadlock-potential than I am happy with. TThread.Synchronize has been re-written at least twice. I used it once, on D3, and had problems. I looked at how it worked. I never used it again.
2) I the design I use most often. I use app-lifetime threads, (or thread pools), create inter-thread comms objects and queue them to background threads using a producer-consumer queue based on a TObjectQueue descendant. The background thread/s operate on the data/methods of the object, store results in the object and, when complete, PostMessage() the object, (cast to lParam) back to the main thread for GUI display of results in a message-handler, (cast the lParam back again). The background threads in the main GUI thread then never have to operate on the same object and never have to directly access any fields of each other.
I use a hidden window of the GUI thread, (created with RegisterWindowClass and CreateWindow), for the background threads to PostMessage to, comms object in LParam and 'target' TwinControl, (usually a TForm class), as WParam. The trivial wndproc for the hidden window just uses TwinControl.Perform() to pass on the LParam to a message-handler of the form. This is safer than PostMessaging the object directly to a TForm.handle - the handle can, unfortunately, change if the window is recreated. The hidden window never calls RecreateWindow() and so its handle never changes.
Producer-consumer queues 'out from GUI', inter-thread comms classes/objects and PostMessage() 'in to GUI' WILL work well - I've been doing it for decades.
Re-using the comms objects is fairly easy too - just create a load in a loop at startup, (preferably in an initialization section so that the comms objects outlive all forms), and push them onto a P-C queue - that's your pool. It's easier if the comms class has a private field for the pool instance - the 'releaseBackToPool' method then needs no parameters and, if there is more than one pool, ensures that the objects are always released back to their own pool.
3) Can't really improve on David Hefferman's comment. Just don't do it.
You can implement the pattern questioned by using OTL as demonstrated by the OTL author here
You could communicate data between threads as messages.
Thread1:
allocate memory for a data structure
fill it in
send a message to Thread2 with the pointer to this structure (you could either use Windows messages or implement a queue, insuring its enque and dequeue methods don't have race conditions)
possibly receive a response message from Thread2...
Thread2:
receive the message with the pointer to the data structure from Thread1
consume the data
deallocate the data structure's memory
possibly send a message back to Thread1 in a similar fashion (perhaps reusing the data structure, but then you don't deallocate it)
You may end up with more than 1 non-GUI thread if you want your GUI not only live, but also responding to some input, while the input that takes long time to be processed is being processed.

Delphi: How to lock "Socket.Write" and unlock?

I have several clients, who writes to one socket (not port), when they write together, I receive the garbage, all data from all clients are merged.
all clients are in the same program in Threads.
I need to lock write()
ASocket.Connection.Socket.LOCK; // need to be thread safe
ASocket.Connection.Socket.Write(buf);
ASocket.Connection.Socket.UNLOCK; // need to be thread safe
How can I do it ?
Thanks.
Delphi 2010, Indy 10, Win7
You can use TCriticalSection (SyncObjs unit): put the Write between Enter and Leave:
CriticalSection.Enter;
try
ASocket.Connection.Socket.Write(buf);
finally
CriticalSection.Leave;
end;
The methods Acquire and Release do the same (doc). Important: if you write to the socket at multiple points of your code, you must use the same object (the one I called CriticalSection in the above example).

Qt objects - am I overusing QMutexLocker?

I have a Qt object that's used by a GUI thread and a networking thread. It looks like:
QString User::Username()
{
QMutexLocker locker(&mutex);
return username;
}
void User::SetUsername(const QString &newUsername)
{
QMutexLocker locker(&mutex);
username = newUsername;
}
QString User::Password()
{
QMutexLocker locker(&mutex);
return password;
}
...
Both the GUI and networking thread may use the object (e.g. to display the username on the screen, and to get the username to send across the network).
I'm worried something is wrong, as every method in the object has a QMutexLocker line, to make it thread safe.
Is it acceptable to use QMutexLocker in this way, or is the code structured badly?
You should be using QReadWriteLock and QReadLocker or QWriteLocker respectively. So no threads will be locked if there are only reading threads.
If there are some fields of the class which are accessed changed very frequently, and which dont change any other state of the class, you might want to give it its own dedicated lock.
I think you may be going about things the wrong way. Serializing each method call will "sort of" work, but it won't reliably handle operations like adding or removing a User object. For example, if your main thread deletes the User object, it won't matter that the network thread is carefully locking a mutex, because after the mutex-lock operation returns, the network thread will then try to access the (now deleted) User object, and trying to read OR write freed memory will cause your app to crash (or worse, just mysteriously do the wrong thing sometimes).
Here's a better way to do it (assuming that the User objects are reasonably small): Instead of having the network thread and the I/O thread share the same User object, and trying to serialize all accesses to the object at the method level, you'd be better off giving a separate copy of each User object to the I/O thread. Then when one thread changes its local copy of the User object, it should send a message to the other thread containing a copy of the updated object, and when the other thread receives the message it can update its local copy to match again. That way each thread has exclusive read/write access to its own local set of User objects, and can read/write them without any locking. This also allows each thread to add or remove objects at will (as long as it sends an update-message to the other thread afterwards, so the other thread will follow suit).
I think a better and cleaner way would be to have a "safe section"
updateUser( User ) {
User.acquireLock()
User.SetUsername(newUsername)
User.Password()
< more operations here >
User.releaseLock()
}
The advantages of this is that you are locking only once the mutex( that is an expensive operation).

Thread context on Delphi

I am creating a server that starts a thread (listening thread). This thread listens for connections and does it's thing. Eventually it may receive some data, that I want to pass to the creator of the server:
My program --> Creates my server --> Creates the listener --> Creates a thread for every client
Now the question is: if I assign a property OnData = procedure (const Received: string) of object; to the server when I create it, and then, this same procedure is passed to the client threads, so when the thread get some data, it will be able to pass it back to the creator of the server. In pseudocode:
//My program
MyServer:= TServer.Create();
MyServer.Ondata:= SomeProcedure;
//The client thread
//When data is received
if (FServer <> nil) then
if Assigned(FServer.Ondata) then
Fserver.Ondata(ReceivedString)..
The questions here are:
1- I understand that if 10 threads execute this procedure at the same time, the procedure will be execute in the client thread context, so is the responsibility of my program (the actual "owner" of the procedure) to synchronize. Is that right?
2- If 10 different threads execute the procedure do I have 10 "instances" of the procedure with it's own data running at the same time?
3- Do I need to protect the OnData on the Server object as well (say, with a critical section), or it's OK to leave it to the "actual" procedure?
Yes. When the thread is running, all the code it runs gets executed within its own thread context, unless that code's been sent to another thread, for example with the Synchronize method.
Almost. You have 10 instances of the TThread object, each with its own data, running at the same time. There's only one copy of the actual code to the procedure, but multiple data objects can use it at once.
Any code that's not thread-safe (that might access the VCL, or that will write to any shared data, or read from shared data that something else might write to) needs to be protected.

Resources