What's the difference between TIdNotify and TIdSync? - delphi

I'm in trouble understanding the real difference between IDSYNC and IDNOTIFY, what means synchronous / asynchronous
in respect to the lines of code I write ?
procedure TForm1.IdTCPServerExecute(AContext: TIdContext);
begin
....
DoSomeThing (TIDNotify) ....
DoSomethingOther(TIDsync) ......
end;
Why can't I be sure that both lines of code are executed within the TCPServer Execute function?
Is there only the risk that a few lines of code are not executed within my TIDSynfunction or how can a Deadloack be explained ?

TIdSync and TIdNotify accomplish the same goal - to execute a piece of code in the context of the main thread - but they do it in different ways.
TIdSync is synchronous. The TIdSync.Synchronize() method blocks the calling thread until after the main thread has called the TIdSync.DoSynchronize() method and it has exited. A deadlock can occur if TIdSync.Synchronize() is called within a server event handler while the main thread is shutting down that server. This is because the main thread is blocked waiting for the server to terminate its threads. But the thread is blocked waiting for the main thread to process the sync request.
TIdNotify is asynchronous. The TIdNotify.Notify() method adds the TIdNotify.DoNotify() method into a background queue and exits immediately, so the calling thread is not blocked. The main thread calls the TIdNotify.DoNotify() method at its leisure. There is no deadlock in this situation.

Related

Delphi creating thread safe writing functions

I'm using Delphi XE in order to create a multi thread application.
I want to create a thread to handle all the writing into a firebird/sqlite database log.
And i want to create several threads that do some jobs and these other threads need to use the writing log thread when they need.
Thread1 = writing log thread
Thread2 = do some math and from time to time use Thread1 to write log.
Thread3 = do some other stuff and from time to time use Thread1 to write log.
and so on
for simplicity I have created a method in thread1 named WriteCollectionLog that all the other thread need to use to write the log into thread1 memory (a collection) and thread1 "onexecute" will handle the real log write into the database. This method is intended to be used like a "fire and forget" method.
now how do i make this thread safe? or can I make it thread safe? (by using TCriticalSection?)
thread2.WriteCollectionLog ...
thread3.WriteCollectionLog ...
procedure Thread1.WriteCollectionLog(aIDWORKFLOW : Integer);
var workItem : TLogFIREBIRD_Item;
begin
try
readWriteCriticalSection.Acquire; <--- this will suspend the calling thread .. like thread2, thread3 and not the thread1?
do stuff;
finally
readWriteCriticalSection.Release;
end;
end;
Regards
Razvan
Just implement what you wrote: only write to the DB from Thread1.
Please don't expect to "call" one thread from another, as you may using "Synchronize" to run some code in the main thread. It would be blocking, which is not what you expect, I guess.
The idea is to have a small in-memory structure, shared between the threads, protected by a critical section. One goal is to keep any critical section as small as possible.
For instance, you may use a TObjectQueue, then Thread2 and Thread3 will push some data to the queue, and Thread1 will wait for some pending data in the Queue, then unqueue it and write it - and if you define a transaction, it will be faster than a naive blocking process. If you just want to write some log content, use a TArray<string>, with an associated lock.

Is there a Multithread version of TMultiReadExclusiveWriteSynchronizer?

With the actual implementation of TMultiReadExclusiveWriteSynchronizer, you must do in the same Thread MyMultiReadExclusiveWriteSynchronizer.beginRead and MyMultiReadExclusiveWriteSynchronizer.endRead
However me I need to call MyMultiReadExclusiveWriteSynchronizer.beginRead in one thread and call MyMultiReadExclusiveWriteSynchronizer.endRead in another thread (this because I use winapi IO completion block)
Is there any way ?

DispatchQueue crashing with main.sync in Swift

Please explain to me why I am getting this crash?
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
in this
DispatchQueue.main.sync {
print("sync")
}
This is my code.
override func viewDidLoad() {
super.viewDidLoad()
print("Start")
DispatchQueue.main.async {
print("async")
}
DispatchQueue.main.sync {
print("sync")
}
print("Finish")
}
NEVER call the sync function on the main queue
If you call the sync function on the main queue it will block the queue as well as the queue will be waiting for the task to be completed but the task will never be finished since it will not be even able to start due to the queue is already blocked. It is called deadlock.
Two (or sometimes more) items — in most cases, threads — are said to be deadlocked if they all get stuck waiting for each other to complete or perform another action. The first can’t finish because it’s waiting for the second to finish. But the second can’t finish because it’s waiting for the first to finish.
You need to be careful though. Imagine if you call sync and target the current queue you’re already running on. This will result in a deadlock situation.
Use sync to keep track of your work with dispatch barriers, or when you need to wait for the operation to finish before you can use the data processed by the closure.
When to use sync?
When we need to wait until the task is finished. F.e. when we are making sure that some function/method is not double called. F.e. we have synchronization and trying to prevent it to be double called until it's completely finished.
When you need to wait for something done on a DIFFERENT queue and only then continue working on your current queue
Synchronous vs. Asynchronous
With GCD, you can dispatch a task either synchronously or asynchronously.
A synchronous function returns control to the caller after the task is completed.
An asynchronous function returns immediately, ordering the task to be done but not waiting for it. Thus, an asynchronous function does not block the current thread of execution from proceeding on to the next function.
#sankalap, Dispatch.main is a serial queue which has single thread to execute all the operations. If we call "sync" on this queue it will block all other operations currently running on the thread and try to execute the code block inside sync whatever you have written. This results in "deadlock".
As per Apple documentation on executing dispatch_sync on a queue you're currently on will crash your code:
Calling this function and targeting the current queue results in
deadlock.
Because the current queue is the main queue, when you continue to call sync on the main queue, the system will understand that current main queue must wait some code complete in current queue, but no code at current queue (main queue), so you wait forever:
Apple document: Calling this function and targeting the current queue results in deadlock.

What happens to main queue/main thread, when a dispatch_sync is issued from main thread targeting another dispatch queue?

Suppose I call the method below on the main thread. If some other thread is doing a write on the array at the time the method is called, the dispatch_sync will block. But it is blocking on another queue (not main queue). When this is blocked, what is the state on the main queue (method cannot move forward until the disaptch_sync returns, but is this treated like a asynchronous call on the main queue). For e.g: will the main queue respond to UI events? If yes, what will happen to the state of the method call when dispatch_sync returns when the reaction to user event is happening?
-(id) objectAtIndex:(NSUInteger)index
{
__block id obj;
dispatch_sync(self.dataAccessQ, ^{
obj = self.embeddedArray[index];
});
return obj;
}
It doesn't matter whether it's the main queue or not. Whatever queue is used to call objectAtIndex: will block on the dispatch_sync call until it completes.
If you call this code on the main queue, it blocks like any other queue. During that time, no user events will be processed. The UI will appear locked during that time. When done, the UI will again work as normal.
No, the main queue is akin of blocked, too.
The main queue is bound to the main thread. Every thread can execute one and only one control flow at a time. If any code is executed on the main thread, no other code can be executed.
Therefore waiting for the result of an operation subscripted to another queue will block the waiting thread. (Not a parallel Q!) This is why we have completion handlers.
Instead of returning an object, add a parameter for a completion handler to your method and call that inside the block at the end.

topic regarding POSIX thread

How does a thread knows when to exit?
SITUATION:
-while the main program must wait for the threads to run to completion.
-This can be done by using a prototype function called pthread_join.
-after all, a call to this function waits for the termination of the thread whose id is given by thread itself.
After you have called pthread_join(ptherad_t &var)the main will wait untill all the threads for which you have called join have exited.
once all the threads are completed their tasks,
when it calls pthread_exit(NULL) main will exit.
inside the thread after its task is completed you need to call pthread_exit(NULL) which will stop the excution of the thread.But this is not mandatory and the thread can simply return which means that the thread has completed.
when it(thread) calls pthread_exit(NULL),the calling thread will exit.

Resources