# 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.

Use `TaskQueue` when work must be queued from multiple threads but executed by one blocking task loop.

### 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

```cpp
// Queue a function pointer
ThreadPoolLite::Queue(someFunction);

// Queue a lambda expression
ThreadPoolLite::QueueLambda([]() {
    // Work to be done in background thread
});
```

## Task Queue Operations

`TaskQueue` owns a FIFO task list and a semaphore-backed blocking loop. Call `QueueTask` from any thread, run `RunTaskQueue` on the thread that should execute the work, and call `QueueExitTask` to leave the loop after already queued tasks are complete.

```cpp
auto queue = Ptr(new TaskQueue);
auto thread = Ptr(Thread::CreateAndStart([=]()
{
    queue->RunTaskQueue();
}, false));

queue->QueueTask([]()
{
    // Runs on the task queue thread
});
queue->QueueExitTask();
```

Use `TaskQueue` instead of `ThreadPoolLite` when the order and single-threaded execution context of tasks matters.

## 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. Use `TaskQueue` when a long-lived single-threaded task loop is required.

### 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`. `TaskQueue` is the alternative when multiple callers should enqueue work to one owner thread.

This approach provides better resource management and avoids the complexities of manual thread synchronization.

## Extra Content

### Threading Best Practices

1. **Prefer Thread Pool**: Use `ThreadPoolLite` for most concurrent operations, and use `TaskQueue` for serialized owner-thread work
2. **Avoid Thread Creation**: Manual thread creation adds overhead and complexity
3. **Use Synchronization Primitives**: Combine threading with proper synchronization objects
4. **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 `Mutex` for cross-process synchronization
- Combine with `CriticalSection` for in-process protection
- Integrate with `EventObject` for thread coordination
- Apply `ConditionVariable` for complex waiting scenarios
