To start a new thread, the BeginThread function should be used. It has one mandatory argument:
the function which will be executed in the new thread. The result of the function is the
exit result of the thread. The thread function can be passed a pointer, which can be
used to access initialization data: The programmer must make sure that the data is
accessible from the thread and does not go out of scope before the thread has accessed
it.
Type
TThreadFunc = function(parameter : pointer) : ptrint;
function BeginThread(sa : Pointer;
stacksize : SizeUInt;
ThreadFunction : tthreadfunc;
p : pointer;
creationFlags : dword;
var ThreadId : TThreadID) : TThreadID;
This rather complicated full form of the function also comes in more simplified forms:
function BeginThread(ThreadFunction : tthreadfunc) : TThreadID;
function BeginThread(ThreadFunction : tthreadfunc;
p : pointer) : TThreadID;
function BeginThread(ThreadFunction : tthreadfunc;
p : pointer;
var ThreadId : TThreadID) : TThreadID;
function BeginThread(ThreadFunction : tthreadfunc;
p : pointer;
var ThreadId : TThreadID;
const stacksize: SizeUInt) : TThreadID;
The parameters have the following meaning:
-
ThreadFunction
- is the function that should be executed in the thread.
-
p
- If present, the pointer p will be passed to the thread function when it is started. If p is
not specified, Nil is passed.
-
ThreadID
- If ThreadID is present, the ID of the thread will be stored in it.
-
stacksize
- if present, this parameter specifies the stack size used for the thread.
-
sa
- signal action. Important for linux only.
-
creationflags
- these are system-specific creation flags. Important for Windows and os/2
only.
The newly started thread will run until the ThreadFunction exits, or until it explicitly calls the
EndThread function:
procedure EndThread(ExitCode : DWord);
procedure EndThread;
The exitcode can be examined by the code which started the thread.
The following is a small example of how to program a thread:
{$mode objfpc}
uses
sysutils {$ifdef unix},cthreads{$endif} ;
const
threadcount = 100;
stringlen = 10000;
var
finished : longint;
threadvar
thri : ptrint;
function f(p : pointer) : ptrint;
var
s : ansistring;
begin
Writeln(’thread ’,longint(p),’ started’);
thri:=0;
while (thri<stringlen) do
begin
s:=s+’1’;
inc(thri);
end;
Writeln(’thread ’,longint(p),’ finished’);
InterLockedIncrement(finished);
f:=0;
end;
var
i : longint;
begin
finished:=0;
for i:=1 to threadcount do
BeginThread(@f,pointer(i));
while finished<threadcount do ;
Writeln(finished);
end.
The InterLockedIncrement is a thread-safe version of the standard Inc function.
To provide system-independent support for thread programming, some utility functions are
implemented to manipulate threads. To use these functions the thread ID must have been retrieved
when the thread was started, because most functions require the ID to identify the thread on
which they should act:
function SuspendThread(threadHandle: TThreadID): dword;
function ResumeThread(threadHandle: TThreadID): dword;
function KillThread(threadHandle: TThreadID): dword;
function WaitForThreadTerminate(threadHandle: TThreadID;
TimeoutMs : longint): dword;
function ThreadSetPriority(threadHandle: TThreadID;
Prio: longint): boolean;
function ThreadGetPriority(threadHandle: TThreadID): Integer;
function GetCurrentThreadId: dword;
procedure ThreadSwitch;
The meaning of these functions should be clear:
-
SuspendThread
- Suspends the execution of the thread.
-
ResumeThread
- Resumes execution of a suspended thread.
-
KillThread
- Kills the thread: the thread is removed from memory.
-
WaitForThreadTerminate
- Waits for the thread to terminate. The function returns when
the thread has finished executing, or when the timeout expired.
-
ThreadSetPriority
- Sets the execution priority of the thread. This call is not always
allowed: your process may not have the necessary permissions to do this.
-
ThreadGetPriority
- Returns the current execution priority of the thread.
-
GetCurrentThreadId
- Returns the ID of the current thread.
-
ThreadSwitch
- Allows other threads to execute at this point. This means that it can cause
a thread switch, but this is not guaranteed, it depends on the OS and the number of
processors.