Class AThread

DescriptionHierarchyFieldsMethodsProperties

Unit

Declaration

type AThread = class(AnObject)

Description

This class represents a single thread of execution within a larger process. It is defined because, as of its creation, the FPC runtime on Linux systems did not seem to implement the TThread class completely. In particular, the Linux RTL routines did not implement System.suspendThread.

The order in which thread methods are executed for instances of AThread and its descendants is:

  1. AThread.new

    1. AThread.init

  2. AThread.split

    1. AThread.prepareToSplit

    2. AThread.execute

    3. AThread.prepareToJoin

  3. AThread.free

    1. AThread.destroy

Hierarchy

Overview

Fields

Protected myHandle: TThreadID;
Protected myStatus: TThreadStatus;
Protected myReturnValue: integer;

Methods

Public function init: boolean; override;
Public destructor destroy; override;
Public function prepareToSplit: boolean; virtual;
Public function split(const desiredStackSize: longword = thrdDefaultStackSize): boolean; virtual;
Public procedure execute; virtual; abstract;
Public procedure cancel; virtual;
Public procedure prepareToJoin; virtual; abstract;
Public function join(const timeout: integer = 0): longword; virtual;
Public procedure yield; virtual;
Public function suspend: integer; virtual;
Public function resume: integer; virtual;
Public function handle: TThreadID; virtual;
Public function status: TThreadStatus; virtual;
Public function returnValue: integer; virtual;
Public function priority: integer; virtual;
Public function setPriority(const newPriority: integer): integer; virtual;

Description

Fields

Protected myHandle: TThreadID;

Stores the handle of the thread

Protected myStatus: TThreadStatus;

Indicates the thread's current status

Protected myReturnValue: integer;

Stores the thread return value

Methods

Public function init: boolean; override;

Initializer

Public destructor destroy; override;

Destructor.

This method frees the thread instance. If the thread is currently executing, the routine will cancel its execution.

Public function prepareToSplit: boolean; virtual;

Prepare the thread instance for concurrent execution.

This method can be used to perform any last-minute allocations or initializations that the thread instance may require before it is executed as a separate thread. The method should return True to indicate that the instance is ready to begin concurrent execution and False to indicate that it is not.

This method is called automatically by AThread.split.

The base implementation of this method always returns True.

Public function split(const desiredStackSize: longword = thrdDefaultStackSize): boolean; virtual;

Begin concurrent execution of the thread.

The base implementation of this method first calls Self.prepareToSplit. If that method returns successfully, the routine then attempts to allocate a memory area for the new thread's stack that is at least the number of bytes specified by desiredStackSize. If the attempt is successful, then the code specified by Self.execute is executed in the newly-separated thread.

This method will return immediately, regardless of whether or not the new thread of execution was successfully created.

Returns

True if the new thread was spawned successfully; False otherwise. The method will return False if a stack could not be allocated for the new thread, or if Self.prepareToSplit returns False.

Public procedure execute; virtual; abstract;

Execute the thread.

This method is meant to be overridden by descendant classes, where it will specify the code that is to be executed in an independent thread. This method will not return until the thread rejoins the main process.

This method should set the value of Self.returnValue before it finishes.

Public procedure cancel; virtual;

Cancel thread execution.

This method causes execution of the thread to end by calling System.killThread. When that routine returns, the method sets Self.status to THREAD_STATUS_CANCELLED and then calls Self.prepareToJoin to clean up after the thread.

Public procedure prepareToJoin; virtual; abstract;

Clean up after concurrent execution of the thread instance.

This method can be used to deallocate items that are not required by the thread instance when it is not running as its own separate thread. It is called automatically when Self.execute returns.

The base implementation of this routine does nothing.

Public function join(const timeout: integer = 0): longword; virtual;

Wait for the thread to finish executing.

This method will only work for those threads that are marked as joinable on creation. The base implementation of AThread always creates threads that are marked as joinable.

This method calls System.waitForThreadTerminate().

Parameters
timeout,
if specified, indicates the number of milliseconds to wait for the thread to finish. The method will return with an error code if the the thread did not finish execution in the allotted time. Note that not all operating systems support this idea, and so it is possible that calling this method will cause the caller to wait indenfinitely, even if a timeout period is specified.
Returns

Zero (0) on success; a non-zero value on failure. "Success" means that the thread ended within the amount of time specified by timeout.

Public procedure yield; virtual;

Signal to the operating system that the thread will yield processor time to other threads.

This method may or may not cause the operating system to switch execution to another thread, depending upon whether there are other threads that require execution, and the way in which those threads are distributed by the system across the available processors.

This method calls System.threadSwitch().

Public function suspend: integer; virtual;

Suspend the thread.

This method halts execution of the thread until it is awakened by a call to AThread.continue. For threads that must wait on an external event, this method makes more efficient use of processor time than simply executing a loop.

This method does not make use of System.suspendThread because, as of this writing, that function is not implemented in the Linux version of the Free Pascal RTL and its usage on Windows 7 systems caused the programs using it to crash.

On Windows targets, the method forces Windows to create a message queue for the thread, then relinquishes control of the processor until a specific message is received at the thread's message queue. The message used by the base implementation of this routine is WM_USER; the routine calls GetMessage(), filtering the queue specifically for the expected message, which effectively suspends the thread until the message is received.

On Linux targets, the method uses signals. The kernel is instructed to wake the thread when a specific signal is sent, then the processor is relinquished. The signal used by the base implementation of this routine is SIGUSR1. The method calls sigaddset() to specify the signal desired, then calls sigwait(). sigsuspend() is not used because, in practice (and contrary to the documentation for the function), the entire process was suspended instead of just the running thread.

Public function resume: integer; virtual;

Resume the thread.

This method is designed to awaken a thread instance that has been suspended by means of AThread.suspend; it will not necessarily work if the thread has been suspended by another means. This is because we are not able to use the FPC RTL routines to obtain a consistent result.

Instead of calling System.resumeThread, which as of this writing is not implemented consistently across the platforms that FPC supports, this method sends a message or a signal to the thread, depending on the target system.

On Windows targets, the method uses PostThreadMessage() to send the WM_USER message to the thread's queue; this queue is created automatically for the thread in response to the actions undertaken by Self.suspend.

On Linux targets, the method uses pthread_kill() to send the SIGUSR1 signal to the thread.

Both cases result in the thread being scheduled for execution once more. Note that the there is no specific way to determine WHEN the thread will resume execution, only that the underlying operating system will eventually execute it.

Public function handle: TThreadID; virtual;

Retrieve the handle or identifier assigned to the thread.

The meaning of the value returned by this method will depend on the underlying operating system.

Public function status: TThreadStatus; virtual;

Retrieve the current status of the thread.

The value returned by this method will be one of those defined by TThreadStatus, depending on the current state of the thread:

  • If the thread has been newly created, but has not yet been executed, the code returned by this method will be THREAD_STATUS_NONE.

  • If the thread is currently being executed, the code returned will be THREAD_STATUS_RUNNING.

  • If the thread has been suspended by a call to AThread.suspend, the code returned will be THREAD_STATUS_SUSPENDED.

  • If thread execution has ben cancelled by a call to AThread.cancel, then the code returned will be THREAD_STATUS_CANCELLED.

  • If the thread has been executed and its execution completed successfully, then the code returned will be THREAD_STATUS_COMPLETED. Note that successfully execution of the thread does not mean no errors occurred while the thread was running, only that the thread was cancelled prematurely. The caller should check AThread.returnValue to determine whether errors occurred while the thread was executing.

Public function returnValue: integer; virtual;

Retrieve the return value of the thread.

The value returned by this method is the return value set by Self.execute. If the thread has not yet been executed, the value will be -1. Otherwise, it will depend on the thread implementation – but generally, a value of zero (0) indicates the execution completed successfully, while a nonzero value indicates a failure of some kind.

Public function priority: integer; virtual;

Retrieve the execution priority of the thread.

The meaning of the value returned by this method will depend on the target operating system. Some operating systems may not implement the concept of thread priority.

This method simply calls System.threadGetPriority.

Public function setPriority(const newPriority: integer): integer; virtual;

Set the execution priority of the thread.

The meaning of newPriority will depend on the target operating system. Some operating systems may not implement the concept of thread priority, in which case a call to this method will have no effect.

Returns

The previous value of Self.priority.


Generated by PasDoc 0.13.0 on 2015-05-03 15:25:58