Recent

Author Topic: Playing with thread, memory leaks  (Read 38250 times)

Fred vS

  • Hero Member
  • *****
  • Posts: 1672
    • miXimum is the DJ's best friend
Re: Playing with thread, memory leaks
« Reply #30 on: February 18, 2014, 03:11:28 pm »
Hello.
Im a bit confused...
In conclusion, what is the best way to terminate a thread  ?

Method 1 :
Code: [Select]
Constructor TMyGoodEndThread.Create();
begin
FreeOnTerminate := True; 
...
end;

procedure TMyGoodEndThread.Execute;
begin
...
Terminate;
Waitfor;   
end;

Method 2 :
Code: [Select]
Constructor TMyGoodEndThread.Create();
begin
FreeOnTerminate := false; 
...
end;

procedure TMyGoodEndThread.Execute;
begin
...
Terminate;
Waitfor; 
FreeAndNil; 
end;

Method 3 :
Code: [Select]
Constructor TMyGoodEndThread.Create();
begin
FreeOnTerminate := False; 
...
end;

procedure TMyGoodEndThread.Execute;
begin
...
Terminate;
Waitfor;   
Destroy;
end;

Method 4 :
Code: [Select]
... ?..
Many thanks.
« Last Edit: February 18, 2014, 03:24:26 pm by Fred vS »
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

User137

  • Hero Member
  • *****
  • Posts: 1790
    • Nxpascal home
Re: Playing with thread, memory leaks
« Reply #31 on: February 18, 2014, 03:32:35 pm »
You don't call any of that in Thread.Execute. If you want that thread frees itself when it exits, then you use FreeOnTerminate := True; BUT it means that you cannot use thread.WaitFor; from anywhere for that thread.

As it came apparent, FreeAndNil contains all these; Terminate, WaitFor and Destroy. But the above note applies here too, you cannot use FreeAndNil(thread) if FreeOnTerminate := True;.

Basically FreeOnTerminate is for thread to be standalone. It will not allow any outside control telling it to free itself. You can call thread.Terminate from outside though, but you can't wait for it to close, or know when it did, except with using global variables.
« Last Edit: February 18, 2014, 03:35:25 pm by User137 »

Fred vS

  • Hero Member
  • *****
  • Posts: 1672
    • miXimum is the DJ's best friend
Re: Playing with thread, memory leaks
« Reply #32 on: February 18, 2014, 03:37:50 pm »
Quote
You don't call any of that in Thread.Execute.

OK, now im totally confused. :-[

What is "any of that" for you ?

Thanks..
« Last Edit: February 18, 2014, 03:40:00 pm by Fred vS »
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

User137

  • Hero Member
  • *****
  • Posts: 1790
    • Nxpascal home
Re: Playing with thread, memory leaks
« Reply #33 on: February 18, 2014, 03:49:37 pm »
Working example 1:
Code: [Select]
Constructor TMyGoodEndThread.Create();
begin
FreeOnTerminate := True; 
...
end;

procedure TMyGoodEndThread.Execute;
begin
  while not terminated do begin
    ...
  end;
end;

Working example 2:
Code: [Select]
Constructor TMyGoodEndThread.Create();
begin
FreeOnTerminate := False;
...
end;

procedure TMyGoodEndThread.Execute;
begin
  while not terminated do begin
    ...
  end;
end;

procedure TForm1.CreateThread;
begin
  thread:=TMyGoodEndThread.Create(false);
end;

procedure TForm1.CloseThread;
begin
  FreeAndNil(thread);
end;

Fred vS

  • Hero Member
  • *****
  • Posts: 1672
    • miXimum is the DJ's best friend
Re: Playing with thread, memory leaks
« Reply #34 on: February 18, 2014, 04:10:56 pm »
@ User137

Ok, thanks for your light...

Hum, sorry for the next stupid question :

Is that code OK ? :

Code: [Select]
var
TerminateMyThread : boolean = false;
...
Constructor TMyGoodEndThread.Create();
begin
FreeOnTerminate := True; 
...
end;

procedure TMyGoodEndThread.Execute;
begin
  while TerminateMyThread = false do
begin
    ...
  end;

Terminate;
WaitFor;

end;


I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

Blestan

  • Sr. Member
  • ****
  • Posts: 461
Re: Playing with thread, memory leaks
« Reply #35 on: February 18, 2014, 04:19:47 pm »
with freeonterminate do not call waitfor or terminate ...

when the while loop is exited the thread will be terminated

any cleanup must be done here ... after the main loop

the internal execute call you execute then self.free

and the internal execute is passed to function BeginThread(
  ThreadFunction: TThreadFunc;
  p: pointer;
  var ThreadId: TThreadID;
  const stacksize: SizeUInt;
  creationflags: dword;
):TThreadID;

with creation flags CREATE_SUSPENDED or 0 to execute immediatly or later
to be executed in new created OS thread
« Last Edit: February 18, 2014, 04:27:52 pm by Blestan »
Speak postscript or die!
Translate to pdf and live!

Fred vS

  • Hero Member
  • *****
  • Posts: 1672
    • miXimum is the DJ's best friend
Re: Playing with thread, memory leaks
« Reply #36 on: February 18, 2014, 06:15:15 pm »
Quote
with freeonterminate do not call waitfor or terminate ...

Ok...

Hum, if i use external variabe : TerminateMyThread it is because the (array of) threads are inside a library.

And for foreign-language it is difficult to deal with threads inside a library.
So, using a "simple" variable (like boolean or integer), it is much easier than call Thread.terminate.

So is that code OK ?(is WaitFor done automatically by terminate ?)
Code: [Select]
var
TerminateMyThread : boolean = false;
...
Constructor TMyGoodEndThread.Create();
begin
FreeOnTerminate := True; 
...
end;

procedure TMyGoodEndThread.Execute;
begin
  while TerminateMyThread = false do
begin
    ...
  end;

Terminate;

end;

Thanks
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 1672
    • miXimum is the DJ's best friend
Re: Playing with thread, memory leaks
« Reply #37 on: February 18, 2014, 06:25:00 pm »
Quote
with freeonterminate do not call waitfor or terminate ...

Re-Oooops :
Quote
with freeonterminate do not call waitfor or terminate

Do you mean that the thread will terminate automaticaly with that code, without using terminate : ?
Code: [Select]
var
TerminateMyThread : boolean = false;
...
Constructor TMyGoodEndThread.Create();
begin
FreeOnTerminate := True; 
...
end;

procedure TMyGoodEndThread.Execute;
begin
  while TerminateMyThread = false do
begin
    ...
  end;
...
///// => not needed "terminate" ?
end;
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

User137

  • Hero Member
  • *****
  • Posts: 1790
    • Nxpascal home
Re: Playing with thread, memory leaks
« Reply #38 on: February 18, 2014, 06:35:11 pm »
Terminate is just a procedure that sets variable, that's all:
Code: [Select]
procedure TThread.Terminate;
begin
  FTerminated := True;
end;
You don't need additional global variables for that purpose. You CAN use Terminate when  freeonterminate is true. It will just instruct it to stop, and it will not terminate instantly. But you must be sure that the thread even exists while calling that Terminate, otherwise you could get SIGSEGV (calling class object function for nil object).

Fred vS

  • Hero Member
  • *****
  • Posts: 1672
    • miXimum is the DJ's best friend
Re: Playing with thread, memory leaks
« Reply #39 on: February 18, 2014, 06:47:04 pm »
@ User137 : many thanks for that clear explain. (and i learn much things today, re-thanks).

So, to resume, if
Code: [Select]
FreeOnTerminate := True; then, when
Code: [Select]
procedure TMyGoodEndThread.Execute;
arrives at end; the thread is automatically terminated, waitfor and freedandnil too.

But if
Code: [Select]
FreeOnTerminate := false; then, when
Code: [Select]
procedure TMyGoodEndThread.Execute;
arrives at end; the thread will terminate but waitfor and freedandnil should be called to avoid memory leak.

Yes/No ?

I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

User137

  • Hero Member
  • *****
  • Posts: 1790
    • Nxpascal home
Re: Playing with thread, memory leaks
« Reply #40 on: February 18, 2014, 06:58:37 pm »
So, to resume, if
Code: [Select]
FreeOnTerminate := True; then, when
Code: [Select]
procedure TMyGoodEndThread.Execute;
arrives at end; the thread is automatically terminated, waitfor and freedandnil too.
Roughly yes. Terminated status will be true, and because of that, waitfor would do nothing even if it is called (propably is not called). Object is destroyed from memory but it doesn't automatically set any variable referring to it to nil. That you have to do yourself at the end of Execute (for example global variable "form1.thread:=nil;" if you use such... don't always have to use.).
(And here is another danger when exiting the application. If form1 is freed before thread, you'll get a SIGSEGV trying to set that global var.)

But if
Code: [Select]
FreeOnTerminate := false; then, when
Code: [Select]
procedure TMyGoodEndThread.Execute;
arrives at end; the thread will terminate but waitfor and freedandnil should be called to avoid memory leak.
Yeah, again it is terminated, and it is your responsibility to free the thread. Again waitfor would do nothing on a terminated thread. The Waitfor is there to wait until the thread has finished its Execute method. You can call Start to reuse the same thread multiple times if you want aswell.
« Last Edit: February 18, 2014, 07:02:45 pm by User137 »

Fred vS

  • Hero Member
  • *****
  • Posts: 1672
    • miXimum is the DJ's best friend
Re: Playing with thread, memory leaks
« Reply #41 on: February 18, 2014, 07:02:07 pm »
@ User137 : perfect and many thanks.  ;)
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 1672
    • miXimum is the DJ's best friend
Re: Playing with thread, memory leaks
« Reply #42 on: February 18, 2014, 09:39:47 pm »
Hum, there is still a little shadow in that bright light...

Does it exist ?:   FreeAndNilOnTerminate := True;...  :-[

If no, I would not be against it...  :-X
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

taazz

  • Hero Member
  • *****
  • Posts: 5363
Re: Playing with thread, memory leaks
« Reply #43 on: February 18, 2014, 11:33:05 pm »
sorry this can not exist, you see it is one thing to set an object to nill and a completely different to know how many reference variables are there and how many of them are linked to the thread object. How about setting the onTerminate event and do the clean up in that event?
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

eny

  • Hero Member
  • *****
  • Posts: 1587
Re: Playing with thread, memory leaks
« Reply #44 on: February 18, 2014, 11:53:21 pm »
Hum, there is still a little shadow in that bright light...

Does it exist ?:   FreeAndNilOnTerminate := True;...  :-[
In theory you could define another instance variable that would be a pointer to the variable that contains the thread reference.
At the end of the thread's execute method you could set the thread reference to nil.

The type definition would be something like this
Code: [Select]
  PTMyThread = ^TMyThread;
  TMyThread = class(TThread)
  private
    FThreadRef: PTMyThread;
  public
     //....
  end;

 >:D
All posts based on: Win10 (Win64); Lazarus 1.8.0 'stable' (#56594 win64) unless specified otherwise...