Recent

Author Topic: Multithreaded Application  (Read 18684 times)

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Multithreaded Application
« Reply #15 on: October 09, 2013, 11:20:13 pm »
5- is incorect. The thread that is paused is the thread that the synchronize call was made. Eg. TmyChildThread will pause its execution and add a request for execution in the main threads loop, after the main thread executes the method passed on the synchronize call then the TMyChildThread will continue executing its code. In short do not use synchronize for data exchange between the main thread and the child thread it defits the purpose of a thread use an asynchronous mechanism like postmessage or application.QueueAsyncCall making sure that the data to be accessed by the main thread is properly protected of course or simple use a thread aware data container.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: Multithreaded Application
« Reply #16 on: October 10, 2013, 06:33:48 am »
5- is incorect. The thread that is paused is the thread that the synchronize call was made. Eg. TmyChildThread will pause its execution and add a request for execution in the main threads loop, after the main thread executes the method passed on the synchronize call then the TMyChildThread will continue executing its code. In short do not use synchronize for data exchange between the main thread and the child thread it defits the purpose of a thread use an asynchronous mechanism like postmessage or application.QueueAsyncCall making sure that the data to be accessed by the main thread is properly protected of course or simple use a thread aware data container.
Is I see in OllyDBG , Synchronize procedure compiled by Lazarus Compiler as EnterCriticalSection , SetEvent, PostMessage (mainformhandle,WM_NULL,0,0), WaitForSingleObject. So none of threads is suspended.

I have another questions: is reading (from Execute-method) of some mainform's component property (or some variable, declared in mainform_unit) safe ? If not, why? It just read, so can't currupt data, can it?
WinXP SP3 Pro Russian 32-bit (5.1.2600)

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Multithreaded Application
« Reply #17 on: October 10, 2013, 06:44:40 am »
Exactly my point the child thread waits for the main thread (the call to waitforsingleObject) to signal the completion of execution of the procedure you passed in the synchronize (the event object that is prepared is the signaling mechanism).
While the main goes through the messages and its inner loops and what not the child thread has stopped executing and waits for a signal that everything is ok to resume execution.

As for your question, garlar27's rule number 4 works here.

It is true that if you only read data from a variable but never change them there is no way you can corrupt the data. This includes that all the threads of the application will not change the data as well.

Even if your thread only reads, if the data are changed during the threads execution from some other thread it is highly likely that at some point the thread will read data that are half changed (ee before the other thread has the time to complete the write) and produce wrong results or worst crash the application.

There are of course data that can not be changed in steps ee the write operation is done in a single processor command which can not be interrupted by the thread scheduler (like the boolean that garlar27 mentions in his other post) those if only set  by a single thread are generally safe to be left unprotected.
« Last Edit: October 10, 2013, 07:06:28 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: Multithreaded Application
« Reply #18 on: October 10, 2013, 03:53:44 pm »
...
There are of course data that can not be changed in steps ee the write operation is done in a single processor command which can not be interrupted by the thread scheduler (like the boolean that garlar27 mentions in his other post) those if only set  by a single thread are generally safe to be left unprotected.
Is that valid for Byte and Char types too? I'm curious since I've never needed to read a thread's property of those types from another thread. Thus I never tried that..


5- is incorect. The thread that is paused is the thread that the synchronize call was made. Eg. TmyChildThread will pause its execution and add a request for execution in the main threads loop, after the main thread executes the method passed on the synchronize call then the TMyChildThread will continue executing its code. In short do not use synchronize for data exchange between the main thread and the child thread it defits the purpose of a thread use an asynchronous mechanism like postmessage or application.QueueAsyncCall making sure that the data to be accessed by the main thread is properly protected of course or simple use a thread aware data container.
I see... in the syncronize code below there is no direct evidence that all threads are paused.


Code: [Select]
class procedure TThread.Synchronize(AThread: TThread; AMethod: TThreadMethod);//<---- CLASSES.INC LINE 141
  var
    LocalSyncException: Exception;
  begin
    { do we really need a synchronized call? }
    if GetCurrentThreadID=MainThreadID then
      AMethod()
    else
      begin
        System.EnterCriticalSection(SynchronizeCritSect);
        SynchronizeException:=nil;
        SynchronizeMethod:=AMethod;

        { be careful, after this assignment Method could be already executed }
        DoSynchronizeMethod:=true;

        RtlEventSetEvent(SynchronizeTimeoutEvent);

        if assigned(WakeMainThread) then
          WakeMainThread(AThread);

        { wait infinitely }
        RtlEventWaitFor(ExecuteEvent);
        LocalSyncException:=SynchronizeException;
        System.LeaveCriticalSection(SynchronizeCritSect);
        if assigned(LocalSyncException) then
          raise LocalSyncException;
      end;
  end;

procedure TThread.Synchronize(AMethod: TThreadMethod);//<---- CLASSES.INC LINE 172
  begin
    TThread.Synchronize(self,AMethod);
  end;

function CheckSynchronize(timeout : longint=0) : boolean;//<---- CLASSES.INC LINE 178
  { assumes being called from GUI thread }
  begin
    result:=false;
    { first sanity check }
    if Not IsMultiThread then
      Exit
    { second sanity check }
    else if GetCurrentThreadID<>MainThreadID then
      raise EThread.CreateFmt(SCheckSynchronizeError,[GetCurrentThreadID])
    else
      begin
        if timeout>0 then
          begin
            RtlEventWaitFor(SynchronizeTimeoutEvent,timeout);
          end
         else
           RtlEventResetEvent(SynchronizeTimeoutEvent);

        if DoSynchronizeMethod then
          begin
            DoSynchronizeMethod:=false;
            try
              SynchronizeMethod;
              result:=true;
            except
              SynchronizeException:=Exception(AcquireExceptionObject);
            end;
            RtlEventSetEvent(ExecuteEvent);
          end;
      end;
  end;


taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Multithreaded Application
« Reply #19 on: October 11, 2013, 03:15:23 am »
Is that valid for Byte and Char types too? I'm curious since I've never needed to read a thread's property of those types from another thread. Thus I never tried that..

I have no idea consult your processors manual for multi threading to see which instructions are considered safe. In general it is not the data type that is safe but the assembly produced for that data type so I haven't done any testing on the fpc compiler on the subject and at this moment I can only recommend to protect everything including bytes and booleans.

I see... in the syncronize code below there is no direct evidence that all threads are paused.


of course not that would be counter productive for threads wouldn't it?

Here is a more well written article on the subject http://msdn.microsoft.com/en-us/magazine/cc163744.aspx
It shows the basics.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

sam707

  • Guest
Re: Multithreaded Application
« Reply #20 on: October 11, 2013, 04:58:51 am »
I thought that the only "paused" thread while calling Synchronize, was the one which called Synchronize. None of the others :

if I have 3 Threads named MyThread1 to MyThread3 running, and MyThread2 calls

Synchronize (MainForm.UpdtateProgresss), the MyThread2 only goes into and idle (suspended) state, then the MAIN Thread of the TApplication calls the UpdtateProgress Procedure... but ! --> and I checked with GDB (debugger windows showing threads) MyThread1 and MyThread3 still are awake and working, avoiding data computing bottlenecks.

Finally that is a very productive and nice feature, a feature that I was expecting to work like that.

the Thread calling Synchronize (MyThread2) pauses -giving handshake to TApplication's Main Thread- , none of the others pause
« Last Edit: October 11, 2013, 05:13:47 am by sam707 »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12712
  • FPC developer.
Re: Multithreaded Application
« Reply #21 on: October 11, 2013, 10:49:30 am »
FPC trunk also has queue(), like in D2006+ that doesn't perform that handshake

 

TinyPortal © 2005-2018