CXThread

From cxwiki

Revision as of 02:39, 23 February 2018 by Windwalkr (talk | contribs)

The CXThread class enables the creation of additional native preemptively-scheduled threads of execution. Each process starts with a singular "main thread" (which is NOT backed by a CXThread object) and may start additional threads by creating CXThread objects and starting them executing. The CXThread object must persist until after the thread in question has terminated; an attempt to destroy the CXThread object will block against completion of the thread. Each CXThread object controls a maximum of one native thread.
 
// Construct a CXThread object, providing a (non-unique) label for debugging purposes.
CXThread(const CXString& debugName);

// Start the thread executing.
virtual void Start(void);

// Request that the thread exit, and block until it does.
virtual void Stop(void);

// Request that the thread exit, but does not block.
void Stopping(void);

// Returns whether the thread was executing at the time of the call. Beware of race conditions.
bool IsRunning(void) const;

// Determines whether anybody has requested this thread to stop.
bool WantToExit(void) const;

 

Usage

Deriving from CXThread

A common usage is for an object to derive from CXThread in order to gain its own threaded functionality. The thread may be started at the end of the constructor, from some post-initialisation method, or even on demand in response to other methods being called.

// When creating a CXThread-derived object, override this function to implement the actual threaded functionality.
virtual void Proc(void) = 0;

In this scenario, it is important for the derived object's destructor to Stop() the thread before destroying any other state, to avoid having the thread function attempt to use destroyed state.

Calling a Lambda Function

Alternatively, for cases where a single function should be run in a thread and there is no need for additional state, a CXThread object can be created for a given lambda function. By default, this thread starts execution immediately, however this can be postponed or prevented entirely.

 

static CXThread* CallFunctionInNewThread(cx_function<void (void)> function, const CXString& debugName, bool bShouldStartThread = true);

In this scenario, the caller is responsible for managing the lifetime of the CXThread object, including delete it when done.

Restrictions

It is considered an error to delete or Stop() a CXThread object from within its thread.

Identification

Each currently-executing native thread, including the main thread and threads created outside of cxsource, has a native-assigned ThreadID which may be queried. This is unique at any given instant. CXThreads which are not currently executing do not have valid ThreadIDs.

// Returns the ThreadID of this CXThread.
ThreadID GetThreadID(void) const;

// Returns the ThreadID of the currently executing thread.
static ThreadID GetCurrentThreadID(void);

 

For threads created using CXThread, the CXThread* object may also be queried.

// Returns the currently executing thread.
static CXThread* __nullable GetCurrentThread(void);

 

All CXThread objects have debug names assigned at construction. Other types of thread may have pseudo-names or may have manually registered names.

static const char* GetThreadDebugName(CXThreadID threadID);

 

The main thread is considered special for a number of reasons. It can be identified.

static CXThreadID GetMainThreadID(void);
static bool IsCurrentThreadMainThread(void);