Hello,
Some time ago I wrote my own thread implementation, and recently I went on the lookout for things I've missed in CThreads.pp in the source code of fpc 2.6.0 (FYI this is also the compiler I currently use). This way I found out about threadvar initialization and some other things I didn't know about. Very interesting!
Since my thread class already did everything that was written down in CThreads.pp, I started thinking `Hey, why not just write a thread manager, to get a full implementation?`. So I did this. In this process I discovered several bugs/inconsistencies in both my implementation and that of CThreads.
I'll start off with some strange things first:
- In the source code of CThreads.pp there appears to be no field in
the threadmanager record called `rtlEventSync`. Yet the compiler
complains about the fact that this field is missing in my
declaration of the TThreadManager record. This declaration looks as
follows: `Const ZThreadManager = TThreadManager = (field: value;
........);`.
- On Mac Os X 10.6.8 the compiler complains about the fact that my
equivalent of the Function CBeginThread is incompatible with the one
in the TThreadManager Record (The result types are incompatible,
aswell as the type of ThreadId: Pointer [Linux; this is also what is
typed in the source file] TThreadId [Mac OS X]). This is very
strange 'cause I copied the declaration of every function over from
CThreads.pp. Should be the same, no?
- Declaration of `pthread_key_create` differs from Mac OS X to
linux? Very weird because the documentation for both OS'es says
exactly the same, which is basically this:
`Type TCProcedure = Procedure(arg: Pointer); cdecl;
Function pthread_key_create(key: ppthread_key_t; DestructorFunc:
TCProcedure): cint; cdecl; external name 'pthread_key_create';`Then some things that seem unlogical to me:
- `Procedure IntbasiceventSetEvent` contains a Try...Finally block, while there is no code inbetween that could possibly raise an exception. Why is it there? (are some signals "converted" to an exception? If so, why isn't this in almost every other function as well?)
- Parameters `creationFlags` and `sa` in CBeginThread of CThreads.pp appear to be unused?
- `Procedure CInitCriticalSection` contains the remark `No recursive mutex support :/`; which is quite weird because a recursive mutex behaves *very* differently from a normal mutex. On some implementations this means that you will all of the sudden get deadlocks where you don't expect them. The fix for this would be to remove recursive mutex support for critical sections. A patch for this would be to replace the existing code with the one attached [CInitCriticalSection.pas].
- The types of TRTLCriticalSection and TThreadID are not defined in the same unit as the thread manager, which means that creating custom implementations of these (especially true for critical sections) is impossible. As an example: suppose I want to use an integer for busy waiting as a critical section, I would define TRTLCriticalSection as an integer. Now I am stuck with pthreads' mutex, which is not handy if you want to do this kinda thing with an integer.
And something I haven't yet investigated thoroughly:
- On Max OS X, `sem_open` appears not to be found. This might be a simply typo of mine, but maybe there's someone with the same problem?
Congratulations and thank you for reading this far ;-) If anyone could grant me some insights on one of these points it would be greatly appreciated.
Long days and pleasant nights to you all.
BTW: I only program unix OS'es nowadays, so don't shoot me if I missed some windows specific stuff.
