[Lazarus] Threads

Sven Barth pascaldragon at googlemail.com
Fri Mar 23 10:59:12 CET 2012


Am 23.03.2012 10:25, schrieb Antonio Fortuny:
> Le 22/03/2012 16:20, Mattias Gaertner a écrit :
>>
>> Each thread has its own stack.
>>
>> All threads share the same address space and the same heap.
>>
>> Objects (here: class instances) are created on the heap. The heap is
>> thread safe.
>>
>> The data segment is for constants. They are shared.
>>
> Le 22/03/2012 17:10, Michael Schnell a écrit :
>> Besides what the other said a very basic comment.
>>
>> The location where an object is defined (i.e. within a TThread enabled
>> unit) or who created it (the main line code or the thread code) does
>> not matter. The Concept of classes, objects and instances is a matter
>> of memory allocation and pointers and not a concept of program flow.
>> same is absolutely independent. You can use one instance of a class in
>> one thread and another one in another thread. You can create an
>> instance in one thread and call its procedures and properties by
>> another one. (BTW this results in the fact that its very hard to
>> define something like "Thread-safe" for a class).
> Thanks to you all .
> Trying to be as much clear as possible, there are some sentences:
>
> Assuming this few statements (aka my own rules when writing thread's code):
> a. all thread code+data are encapsulated into a TThread object
> b. "Thread safe" means that there is no overlap of data references from
> thread to thread, the main thread inclusive, and that no references are
> passed outside the thread's control from thread to thread (by the means
> of the owner or global vars for instance)
> c. the thread creator does not interfere in any way with the thread's
> data and methods as soon as the thread has been started (Terminated
> execpted of course)
> d. no function neither procedure calls are made to any function or
> procedure defined outside of the thread control (aka self defined methods)

Ok, I hereby assume the above as given.

> Do you all agree on the following asserts:
> 1. All variables in the thread definition (TThread's private, protected
> and public variables) are "Thread safe" BUT are accessible to the thread
> creator

Yes (though the private vars aren't available to the thread creator if 
the creator and the definition of your TThread descendant reside in 
different units ;) )

> 2. an instance of an object (aka TObject descendant) created into the
> thread's EXECUTE procedure is invisible to all other instances of the
> same object whichever the creator could be (the same thread or other
> threads created with the same thread definition object) and to other
> thread object instances, even when the reference variable of the created
> object is defined into the thread vars (see 1.) provided that all object
> methods do not call any function or procedure outside of the object methods.

If I've understood that correctly: yes

> 3. all variables described in the VAR part of the EXECUTE procedure are
> "Thread safe" (seems obvious)

Yes

> 4. all local variables and constants defined into local Thread object
> methods are "Thread safe" (they are defined into each thread stack for
> the vars and the heap for constants)

It's true for variables. Local constants are defined in a section of the 
executable, so if you have writable constants enabled (only then it's a 
problem) and you write to these constants then the change will be 
reflected in other constants as well. If you don't write to the 
constants than they are safe.

> 5. all useful code a thread needs should be encapsultated into a TObject
> descendant and instantiated within the thread's space.

Note necessarily. You can also call global procedures/functions that 
don't rely on global state (e.g. IntToStr, etc.). If you want to call 
functions/procedures that rely on the state (e.g. some registration 
systems for classes) you'll need to synchronize the access.

> 6. all methods defined in the thread's definition, aprat from the
> EXECUTE procedure (obvious !), run into the thread creator space (the
> one which instantiates the thread, aka does something like wThread :=
> TMyThread.Create (False) )

I don't know whether I understood you correctly, but if you have this:

=== example begin ===

type
   TTestThread = class(TThread)
   protected
     procedure Execute; override;
   public
     procedure DoSomething;
   end;

procedure TTestThread.Execute;
begin
   DoSomething;
end;

procedure TTestThread.DoSomething;
begin
   Writeln('Something');
end;

begin
   with TTestThread.Create(True) do begin
     FreeOnTerminate := True;
     Start;
   end;
end.

=== example end ===

Then (to my understandment of your assertion) your assertion is wrong, 
because DoSomething is (although it is public) only called in context of 
Execute (Note: Not that you should make such a method public if you 
don't need to, but this is merely an example).

Regards,
Sven




More information about the Lazarus mailing list