Sven Barth schrieb:
Am 25.08.2010 23:07, schrieb José Mejuto:
On the other hand, if Unix needs one thread creation then it should be
automagically done in the initialization section of cthreads, do not ?
SB>  This might indeed be a solution.

If windows have the same problem, threading system should be
initialized in... somewhere automagically as windows multithread is
always present.


This only solves one point (but is needed nevertheless).

As I've showed in the last message to Alexander yesterday evening you need to initialize some things PER THREAD and I don't know whether this can be automised. We might need to ask the FPC devs for help regarding this. Perhaps the first time a threadvar in this new thread is accessed might be a good possibilty, but I don't know (yet) how we could track whether this is the first call, because threadvars are not yet allocated (hen-egg-problem). I'll have to take a deeper look into the threading system on Win32 :)

Regards,
Sven

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).

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; B) Make the runtime aware that your application uses multiple threads in the first line of your application (.dpr):
IsMultithread:=true;

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

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;


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.


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

Reply via email to