AThreads: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: AThreads
| Old | New | Line | |
|---|---|---|---|
| 1 | + | This page is about the threading implementation for Amiga-like systems in Free Pascal, which supports [[Amiga]], [[MorphOS]] and [[AROS]]. AThreads unit is available since Free Pascal 3.0. | |
| 2 | + | ||
| 3 | + | *(Amiga only)* | |
| 4 | + | ||
| 5 | + | *(AROS only)* | |
| 6 | + | ||
| 7 | + | *(MorphOS only)* | |
| 8 | + | ||
| 9 | + | ## General overview | |
| 10 | + | ||
| 11 | + | Amiga-like systems don't support threads, so AThreads emulates threading with separate processes. This is not an issue in general, because Amiga-like systems are not memory protected and use a shared address space. Therefore Amiga processes are barely more than threads on other systems. However, they still have some unique properties, which have to be kept in mind when one uses threading on Amiga-like systems. For the most important ones, read below. | |
| 12 | + | ||
| 13 | + | ## Usage | |
| 14 | + | ||
| 15 | + | Much like Unix systems, Amiga-like systems doesn't have a default ThreadManager in the System unit. Therefore, AThreads unit, which provides a native ThreadManager **must** be included as the **first** unit in the main program's uses clause. Similarly to Unix systems' CThreads unit. | |
| 16 | + | ||
| 17 | + | ``` pascal | |
| 18 | + | program myapp; | |
| 19 | + | ||
| 20 | + | uses | |
| 21 | + | {$IFDEF HASAMIGA} | |
| 22 | + | AThreads, | |
| 23 | + | {$ENDIF} | |
| 24 | + | // additional units... | |
| 25 | + | ``` | |
| 26 | + | ||
| 27 | + | ## Stack | |
| 28 | + | ||
| 29 | + | Unlike other systems, where a 4MB default stack is enforced for subthreads, with AThreads they inherit the stack size of the main thread instead. AThreads follows the Delphi convention and provides the **const STACK_SIZE_PARAM_IS_A_RESERVATION** to specify as a flag for *BeginThread*, to change the default allocation. You can use the **{\$MEMORY}** directive to change the stack size for the main thread. For TThread-based subthreads, there's no way to change the inherited stack size directly, the stacksize argument of the constructor does *NOT* work currently. This is to be fixed in the future. | |
| 30 | + | ||
| 31 | + | ## Terminating threads | |
| 32 | + | ||
| 33 | + | Amiga-like systems won't clean up the subthreads when the main process exits, since the threads are individual processes there. Therefore it's unsafe to: | |
| 34 | + | ||
| 35 | + | - trying to directly exit the app from a subthread | |
| 36 | + | - not exiting running threads properly, before the main thread attempts to exit | |
| 37 | + | ||
| 38 | + | AThreads has some protection to wait the running subthreads to exit on the main process' termination. In these cases, this protection will cause a deadlock, and the app will wait forever to exit. Otherwise the system would free the main process' code segment on exit, which is shared with the other still running processes, and this condition would most likely cause a system crash immediately. | |
| 39 | + | ||
| 40 | + | Additionally, please note that the timeout argument of **WaitForThreadTerminate** function is *NOT* supported. This is similar to CThreads on Unix systems, where it is also not supported. | |
| 41 | + | ||
| 42 | + | ## Library usage in subthreads | |
| 43 | + | ||
| 44 | + | Some shared libraries (like *bsdsocket.library*, see below) in the Amiga environment requires to be opened per process. If you interface to these libraries, the RTL provides the following functions to allow you to hook the Open/Close code for these libraries into threading: | |
| 45 | + | ||
| 46 | + | ``` pascal | |
| 47 | + | Procedure AddThreadInitProc(Proc: TProcedure); | |
| 48 | + | Procedure AddThreadExitProc(Proc: TProcedure); | |
| 49 | + | ``` | |
| 50 | + | ||
| 51 | + | For a working example, see the Amiga-specific implementation of the *sockets* unit. | |
| 52 | + | ||
| 53 | + | ## bsdsocket.library issue | |
| 54 | + | ||
| 55 | + | *bsdsocket.library* which provides a BSD-style network API on Amiga-like systems, needs to be opened per process (therefore per subthread with AThreads). Additionally, socket handles cannot be shared among threads directly. The library provides several functions and constants to pass socket-handles among threads: | |
| 56 | + | ||
| 57 | + | ``` pascal | |
| 58 | + | { Definition for Release(CopyOf)Socket unique id } | |
| 59 | + | const | |
| 60 | + | UNIQUE_ID = -1; | |
| 61 | + | ||
| 62 | + | { Amiga-specific functions for passing socket descriptors between threads (processes) } | |
| 63 | + | function ObtainSocket(id: LongInt; domain: LongInt; _type: LongInt; protocol: LongInt): LongInt; | |
| 64 | + | function ReleaseSocket(s: LongInt; id: LongInt): LongInt; | |
| 65 | + | function ReleaseCopyOfSocket(s: LongInt; id: LongInt): LongInt; | |
| 66 | + | ``` | |
| 67 | + | ||
| 68 | + | These are declared in the *sockets* unit. There's no way to hide this functionality and make it transparent without a major performance hit, so networking code which uses threads simply has to be adapted to this Amiga behavior. For the documentation of these functions, see the SDK of your system. | |
| 69 | + | ||
| 70 | + | ## task^.tc_UserData issue | |
| 71 | + | ||
| 72 | + | Amiga-like systems provide a pointer-sized field in their task structure for the task itself to use, which is called *tc_UserData*. AThreads currently overwrites this field, so it's no longer available to the user program. This behavior is likely to be changed in the future, but mixing AThreads and Amiga-API threading solutions is unsafe anyway. (Note that FPC programs can still use *tc_UserData*, but not together with AThreads unit.) | |
| 73 | + | ||
| 74 | + | ## threadvars | |
| 75 | + | ||
| 76 | + | Threadvars are fully supported, however they have a quite large performance penalty compared to normal global variables. It's advised to cache threadvars in local variables when used extensively in a performance-critical function. | |
| 77 | + | ||
| 78 | + | ## RTL Events | |
| 79 | + | ||
| 80 | + | RTL events are currently unsupported. They will be implemented in the future. | |
| 81 | + | ||
| 82 | + | --- | |
| 83 | + | *From the Free Pascal wiki, page "AThreads", as it stood on 2015-07-05 after a change by Molly, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* | |
| 84 | + | Category: AmigaOS |
