Threading Controls
The Threading tab provides 8 controls for concurrent programming: threads, synchronization primitives, thread pools, and inter-thread communication channels. All controls are cross-platform and use native OS threading facilities.
TThread CT_THREAD = 63
Executes code in a separate OS thread. The primary building block for concurrent operations.
| Property | Type | Default | Description |
nPriority | Numeric | 0 | Thread priority (-2 lowest to +2 highest) |
lFreeOnTerminate | Logical | .F. | Automatically destroy object when thread ends |
lRunning | Logical | .F. | Thread is currently executing (read-only) |
lFinished | Logical | .F. | Thread has completed (read-only) |
nThreadId | Numeric | 0 | OS thread identifier (read-only) |
| Event | Category | Description |
OnExecute | Lifecycle | Code to run in the thread (required) |
OnTerminate | Lifecycle | Thread finished execution (called on main thread) |
| Method | Description |
Start() | Begin thread execution |
Wait( nTimeout ) | Wait for thread to finish. Optional timeout in ms |
Cancel() | Request cooperative cancellation |
| Platform | Native Implementation |
| Windows | CreateThread / _beginthreadex |
| macOS | pthread_create |
| Linux | pthread_create |
TMutex CT_MUTEX = 64
Mutual exclusion lock. Ensures only one thread accesses a shared resource at a time.
| Method | Description |
Lock() | Acquire the mutex. Blocks if already locked by another thread |
Unlock() | Release the mutex |
TryLock() | Attempt to acquire without blocking. Returns .T. if acquired |
| Platform | Native Implementation |
| Windows | CRITICAL_SECTION |
| macOS | pthread_mutex_t |
| Linux | pthread_mutex_t |
TSemaphore CT_SEMAPHORE = 65
Counting semaphore. Controls access to a pool of shared resources with a limited count.
| Property | Type | Default | Description |
nInitialCount | Numeric | 0 | Initial semaphore count |
nMaxCount | Numeric | 1 | Maximum semaphore count |
| Method | Description |
Wait( nTimeout ) | Decrement count. Blocks if count is zero. Optional timeout in ms |
Signal() | Increment count. Wakes one waiting thread |
TCriticalSection CT_CRITICALSECTION = 66
Lightweight synchronization primitive. Faster than TMutex for protecting short code sections within the same process.
| Method | Description |
Enter() | Enter the critical section. Blocks if another thread is inside |
Leave() | Leave the critical section |
TryEnter() | Attempt to enter without blocking. Returns .T. if entered |
TThreadPool CT_THREADPOOL = 67
Manages a pool of reusable worker threads. Submit tasks to the pool instead of creating individual threads.
| Property | Type | Default | Description |
nMinThreads | Numeric | 2 | Minimum number of worker threads |
nMaxThreads | Numeric | 8 | Maximum number of worker threads |
nQueueSize | Numeric | 256 | Maximum pending task queue size |
nActiveThreads | Numeric | 0 | Currently active worker threads (read-only) |
nPendingTasks | Numeric | 0 | Tasks waiting in the queue (read-only) |
| Event | Category | Description |
OnTaskComplete | Lifecycle | A task finished execution. Params: xResult, nTaskId |
OnError | Error | A task raised an error. Params: oError, nTaskId |
| Method | Description |
Submit( bTask ) | Add a task (code block) to the queue. Returns nTaskId |
WaitAll( nTimeout ) | Wait for all pending tasks to complete |
Shutdown() | Stop all threads after completing pending tasks |
TAtomicInt CT_ATOMICINT = 68
Lock-free atomic integer. Provides thread-safe counter operations without explicit locking.
| Method | Description |
Inc() | Atomically increment by 1. Returns new value |
Dec() | Atomically decrement by 1. Returns new value |
Get() | Read current value |
Set( nValue ) | Atomically set to nValue |
CompareExchange( nExpected, nNew ) | If current == nExpected, set to nNew. Returns .T. if swapped |
Add( nValue ) | Atomically add nValue. Returns new value |
| Platform | Native Implementation |
| Windows | InterlockedIncrement / InterlockedCompareExchange |
| macOS | __atomic builtins (GCC/Clang) |
| Linux | __atomic builtins (GCC/Clang) |
TCondVar CT_CONDVAR = 69
Condition variable. Allows threads to wait until a particular condition is signaled by another thread.
| Method | Description |
Wait( oMutex, nTimeout ) | Release mutex and wait for signal. Re-acquires mutex on wake. Optional timeout in ms |
Signal() | Wake one waiting thread |
Broadcast() | Wake all waiting threads |
| Platform | Native Implementation |
| Windows | CONDITION_VARIABLE |
| macOS | pthread_cond_t |
| Linux | pthread_cond_t |
TChannel CT_CHANNEL = 70
Thread-safe message channel for inter-thread communication. Inspired by Go channels and CSP concurrency.
| Property | Type | Default | Description |
nBufferSize | Numeric | 0 | Buffer capacity (0 = unbuffered/synchronous) |
lClosed | Logical | .F. | Channel has been closed (read-only) |
| Method | Description |
Send( xValue ) | Send a value to the channel. Blocks if buffer is full |
Receive() | Receive a value from the channel. Blocks if empty |
TryReceive( @xValue ) | Non-blocking receive. Returns .T. if a value was available |
Close() | Close the channel. No more values can be sent |
| Event | Category | Description |
OnReceive | Data | Value received (alternative to polling). Params: xValue |
Code Example: Producer-Consumer Pattern
// Producer-Consumer pattern using TChannel and TThread
FUNCTION Main()
LOCAL oChannel, oProducer, oConsumer
// Create a buffered channel with capacity 10
oChannel := TChannel():New()
oChannel:nBufferSize := 10
// Producer thread: generates work items
oProducer := TThread():New()
oProducer:lFreeOnTerminate := .T.
oProducer:OnExecute := { || ProduceItems( oChannel ) }
// Consumer thread: processes work items
oConsumer := TThread():New()
oConsumer:lFreeOnTerminate := .T.
oConsumer:OnExecute := { || ConsumeItems( oChannel ) }
// Start both threads
oProducer:Start()
oConsumer:Start()
// Wait for producer to finish, then close channel
oProducer:Wait()
oChannel:Close()
// Wait for consumer to drain remaining items
oConsumer:Wait()
QOut( "All done!" )
RETURN NIL
FUNCTION ProduceItems( oChannel )
LOCAL n
FOR n := 1 TO 100
oChannel:Send( "Task #" + Str( n ) )
QOut( "Produced: Task #" + Str( n ) )
NEXT
RETURN NIL
FUNCTION ConsumeItems( oChannel )
LOCAL xItem
DO WHILE ! oChannel:lClosed .OR. oChannel:TryReceive( @xItem )
xItem := oChannel:Receive()
IF xItem != NIL
QOut( "Consumed: " + xItem )
ENDIF
ENDDO
RETURN NIL
8 Threading Controls
All threading primitives map directly to native OS facilities for maximum performance.
Use TChannel for safe inter-thread communication instead of shared variables with locks.