Recent

Author Topic: [SOLVED] Threads and TRTLCriticalSection  (Read 2199 times)

Pascal

  • Hero Member
  • *****
  • Posts: 932
[SOLVED] Threads and TRTLCriticalSection
« on: February 12, 2017, 07:35:36 pm »
I have a class in which i start a thread.
In some cases this class gets destroyed very soon (before Thread finishes).
Therefore i tried to use a CriticaSection to wait in the destructor for the thread to finish:

Thread:
Code: Pascal  [Select][+][-]
  1. procedure TSVNReader.Execute;
  2. begin
  3.   DebugLn('  SVNReader start %s/%s', [fKISFile.Lib.Name, fKISFile.Name]);
  4.   try
  5.     fKISFile.ThreadReadSVN;
  6.   finally
  7.     DebugLn('  SVNReader stop %d/%s', [fKISFile.Lib.Name, fKISFile.Name]);
  8.     fKISFile.UnlockSVNReader;
  9.   end;
  10. end;
  11.  

Class constructor:
Code: Pascal  [Select][+][-]
  1. constructor TprimeKISFile.Create(...);
  2. begin
  3.   InitCriticalSection(fSVNReaderCriticalSection);
  4.   inherited Create(...);
  5.   ...
  6.   LockSVNReader; // gets unlocked in the end of the threads execute method
  7.   try
  8.     DebugLn('  creating SVNReader %s/%s', [fLib.Name, fName]);
  9.     TSVNReader.Create(Self);
  10.   except
  11.     UnlockSVNReader;
  12.     DebugLn('TSVNReader.Create(%s) failed in Create()', [AFileName]);
  13.   end;
  14.   ...
  15. end;
  16.  

Class destructor:
Code: Pascal  [Select][+][-]
  1. destructor TprimeKISFile.Destroy;
  2. begin
  3.   LockSVNReader;
  4.   DebugLn('Destroy %s/%s', [fLib.Name, fName]);
  5.   ...
  6.   UnlockSVNReader;
  7.   DoneCriticalsection(fSVNReaderCriticalSection);
  8.   inherited Destroy;
  9. end;
  10.  

Lock & Unlock:
Code: Pascal  [Select][+][-]
  1. procedure TprimeKISFile.LockSVNReader;
  2. begin
  3.   EnterCriticalsection(fSVNReaderCriticalSection);
  4.   DebugLn('%s/%s SVNReader locked', [fLib.Name, fName]);
  5. end;
  6.  
  7. procedure TprimeKISFile.UnlockSVNReader;
  8. begin
  9.   DebugLn('%s/%s SVNReader unlocked', [fLib.Name, fName]);
  10.   LeaveCriticalsection(fSVNReaderCriticalSection);
  11. end;
  12.  

I've also use a thread save DebugLn:
Code: Pascal  [Select][+][-]
  1. procedure DebugLn(const S: String; Args: array of const);
  2. begin
  3.   EnterCriticalsection(fLock);
  4.   try
  5.     //WriteLn(fLog, Format(S, Args));
  6.     DebugLogger.DebugLn(S, Args);
  7.   finally
  8.     LeaveCriticalsection(fLock);
  9.   end;
  10. end;
  11.  

when i run my prog it outputs:
Code: Text  [Select][+][-]
  1. t189/SSCX120.CBL SVNReader locked
  2.   creating SVNReader t189/SSCX120.CBL
  3.   SVNReader start t189/SSCX120.CBL
  4.   ThreadReaderSVN t189/SSCX120.CBL
  5. t189/SSCX120.CBL SVNReader locked
  6. Destroy t189/SSCX120.CBL
  7. t189/SSCX120.CBL SVNReader unlocked
  8. d211/SSCX120.CBL SVNReader locked
  9.   creating SVNReader d211/SSCX120.CBL
  10.   SVNReader start d211/SSCX120.CBL
  11.   ThreadReaderSVN d211/SSCX120.CBL
  12. d211/SSCX120.CBL SVNReader locked
  13. Destroy d211/SSCX120.CBL
  14. d211/SSCX120.CBL SVNReader unlocked
  15. h054/SSCX120.CBL SVNReader locked
  16.   creating SVNReader h054/SSCX120.CBL
  17.   SVNReader start h054/SSCX120.CBL
  18.   ThreadReaderSVN h054/SSCX120.CBL
  19. -> access violation here due to access of the first threads execute method to the destroyed object
  20.  

It looks like the critical section has no effect. Output should look like this:
Code: Text  [Select][+][-]
  1. t189/SSCX120.CBL SVNReader locked
  2.   creating SVNReader t189/SSCX120.CBL
  3.   SVNReader start t189/SSCX120.CBL
  4.   ThreadReaderSVN t189/SSCX120.CBL
  5.   SVNReader stop t189/SSCX120.CBL     ***
  6. t189/SSCX120.CBL SVNReader unlocked   ***
  7. t189/SSCX120.CBL SVNReader locked
  8. Destroy t189/SSCX120.CBL

What am i doing wrong?
« Last Edit: February 12, 2017, 07:55:19 pm by Pascal »
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Imants

  • Full Member
  • ***
  • Posts: 198
Re: Threads and TRTLCriticalSection
« Reply #1 on: February 12, 2017, 07:53:47 pm »
I think you should use use references. Thread and every other object which uses TprimeKISFile calls AddRef and when stops using TprimeKISFile calls release. When last reference is released then object is destroyed. It is like interfaces are working

Pascal

  • Hero Member
  • *****
  • Posts: 932
[SOLVED] Re: Threads and TRTLCriticalSection
« Reply #2 on: February 12, 2017, 07:54:19 pm »
After posting i had the solution.
The thread can not leave a critical section if the main thread has already entered it. So the thread itself has to enter the critical section.
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

 

TinyPortal © 2005-2018