On 26.08.2010 20:52, Alexander Grau wrote:

I'm currently trying to summarize all aspects we discussed to add them
to the FreePascal Multithreading wiki page (see below) - did I forget
something that should be mentioned?

Thanks,
Alexander



External threads


To make Free Pascal's threading system to work properly, each newly
created FPC thread needs to be initialized (more exactly, the thread
local storage per thread needs to be initialized so threadvars and heap
are working). That is fully automatically done for you if you use
BeginThread (or indirectly by using the TThread class). However, if you
use threads that were created without BeginThread (i.e. external
threads), additional work (currently) might be required. External
threads also include those that were created in external C libraries
(.DLL/.so).

It's not only initializing the thread local storage (which is Windows only by the way, the threadvar system on e.g. Linux might have a different name), but also the exception and the I/O system


Things to consider when using external threads (might not be needed in
all or future compiler versions):


A) Initialize the FPC's threading system by creating a dummy thread:

{ initialise threading system }
with tc.create(false) do
begin
waitfor;
free;
end;

You should not forget to write how a class of type "tc" looks like :)

B) Make the runtime aware that your application uses multiple threads in
the first line of your application (.dpr):
IsMultithread:=true;


This is not needed. That is set to true automatically if a thread is created inside FPC.

(This will make FPC routines to perform locks here and there.)
C) Do not use external threads at all - use FPC threads.


Should be put at the top of the list ^^

D) If for some reason this doesn't work for you, try this code in your
external thread function:

function ExternalThread(param: Pointer): LongInt; stdcall;
var
tm: TThreadManager;
begin
GetThreadManager(tm);
tm.AllocateThreadVars;
InitThread(100000000);
someFunc(param);
Result:=0;
end;


The number in InitThread is the initial stack length and as I was a bit lazy I simply set it to a huge number. So don't nail me on that one :D

You might also replace the "someFunc(param)" with "{ do something threaded }" or something like that.


How to identify if your code is executed in an external thread context

1. Ask the OS for the ID of the current thread at your application's start

Win32: WriteLn('Thread ID=', GetCurrentThreadID);
Darwin: WriteLn('Thread ID=', GetThreadID); Linux: Writeln('Thread ID=',
TThreadID(pthread_self) );

2. Ask again for the ID of the current thread inside the thread function
and compare this by the result of step 1.

I don't know whether this works (reliably) when the threadvars haven't been allocated yet. I don't even know what happens if you access unallocated threadvars O.o

Regards,
Sven

--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply via email to