3.8 KiB
Multi-threading
Cross-platform threading primitives and synchronization mechanisms for concurrent programming.
Thread Pool Operations
Use ThreadPoolLite::Queue and ThreadPoolLite::QueueLambda for thread pool execution.
Use static functions ThreadPoolLite::Queue or ThreadPoolLite::QueueLambda to run a function in another thread.
ThreadPoolLite Benefits
The thread pool provides several advantages over manual thread creation:
- Automatic thread lifecycle management
- Resource pooling to avoid thread creation overhead
- Better system resource utilization
- Simplified concurrent programming model
Usage Examples
// Queue a function pointer
ThreadPoolLite::Queue(someFunction);
// Queue a lambda expression
ThreadPoolLite::QueueLambda([]() {
// Work to be done in background thread
});
Thread Control Operations
Thread Pausing
Use Thread::Sleep for thread pausing.
Use static function Thread::Sleep to pause the current thread for some milliseconds.
Thread Identification
Use Thread::GetCurrentThreadId for thread identification.
Use static function Thread::GetCurrentThreadId to get an identifier for the OS native thread running the current function.
Manual Thread Creation
Use Thread::CreateAndStart only when thread pool is insufficient.
Thread::CreateAndStart could be used to run a function in another thread while returning a Thread* to control it, but this is not recommended.
Always use ThreadPoolLite if possible.
When to Use Manual Threads
Manual thread creation should only be considered when:
- You need fine-grained control over thread lifecycle
- Thread-specific configurations are required
- The thread pool doesn't meet specific timing requirements
- Working with legacy code that requires direct thread handles
Thread Pool with Synchronization
A ThreadPoolLite call with an EventObject is a better version of Thread::Wait.
This approach provides better resource management and avoids the complexities of manual thread synchronization.
Extra Content
Threading Best Practices
- Prefer Thread Pool: Use
ThreadPoolLitefor most concurrent operations - Avoid Thread Creation: Manual thread creation adds overhead and complexity
- Use Synchronization Primitives: Combine threading with proper synchronization objects
- Handle Exceptions: Ensure proper exception handling in threaded code
Performance Considerations
- Thread Pool: Minimal overhead for task scheduling and execution
- Thread Creation: Significant overhead for creating and destroying threads
- Context Switching: Consider the cost of frequent context switches
- Resource Contention: Be aware of shared resource access patterns
Cross-Platform Considerations
The threading API provides a unified interface across platforms:
- Windows: Uses Windows thread API internally
- Linux: Uses pthread API internally
- Behavior remains consistent across platforms
- Thread IDs are platform-specific but the API is uniform
Memory Management
- Thread pool automatically manages worker threads
- Manual threads require explicit cleanup
- Lambda captures should be carefully managed for thread safety
- Avoid capturing references to stack variables in threaded lambdas
Error Handling
Threading operations can fail due to:
- System resource exhaustion
- Permission restrictions
- Platform-specific limitations
Always check return values and handle potential failures gracefully.
Integration with Synchronization
Multi-threading works best when combined with appropriate synchronization primitives:
- Use with
Mutexfor cross-process synchronization - Combine with
CriticalSectionfor in-process protection - Integrate with
EventObjectfor thread coordination - Apply
ConditionVariablefor complex waiting scenarios