/* * DWN - Desktop Window Manager * retoor * Extensive Abstract Threading Framework * * This module provides a comprehensive, abstract threading system with: * - Lock-free data structures * - Thread pools with work stealing * - Async/await pattern support * - Thread-safe event bus * - Memory barriers and atomic operations */ #ifndef DWN_THREADING_H #define DWN_THREADING_H #include #include #include #include #include /* ============================================================================ * Platform Abstraction Layer * ============================================================================ */ /* Cache line size (commonly 64 bytes on x86_64) */ #define CACHE_LINE_SIZE 64 /* Align to cache line to prevent false sharing */ #define CACHE_ALIGN __attribute__((aligned(CACHE_LINE_SIZE))) /* Memory ordering shortcuts */ #define ATOMIC_RELAXED memory_order_relaxed #define ATOMIC_ACQUIRE memory_order_acquire #define ATOMIC_RELEASE memory_order_release #define ATOMIC_ACQ_REL memory_order_acq_rel #define ATOMIC_SEQ_CST memory_order_seq_cst /* ============================================================================ * Core Types and Status Codes * ============================================================================ */ typedef enum { THREAD_OK = 0, THREAD_ERROR = -1, THREAD_ERROR_NOMEM = -2, THREAD_ERROR_BUSY = -3, THREAD_ERROR_CLOSED = -4, THREAD_ERROR_TIMEOUT = -5, THREAD_ERROR_INVALID = -6 } ThreadStatus; typedef enum { TASK_PRIORITY_CRITICAL = 0, /* UI-critical, must execute immediately */ TASK_PRIORITY_HIGH = 1, /* User-initiated actions */ TASK_PRIORITY_NORMAL = 2, /* Default background work */ TASK_PRIORITY_LOW = 3, /* Maintenance tasks */ TASK_PRIORITY_IDLE = 4, /* Only when system idle */ TASK_PRIORITY_COUNT } TaskPriority; typedef enum { TASK_STATE_PENDING = 0, TASK_STATE_RUNNING = 1, TASK_STATE_COMPLETED = 2, TASK_STATE_CANCELLED = 3, TASK_STATE_ERROR = 4 } TaskState; /* Forward declarations */ typedef struct ThreadPool ThreadPool; typedef struct Task Task; typedef struct Channel Channel; typedef struct Future Future; typedef struct EventBus EventBus; typedef struct AsyncContext AsyncContext; typedef struct Worker Worker; /* ============================================================================ * Task System - Abstract Unit of Work * ============================================================================ */ /* Task function signature - receives user data and cancellation flag */ typedef void (*TaskFunc)(void *user_data, atomic_int *cancelled); /* Callback for task completion (called in worker thread) */ typedef void (*TaskCallback)(Task *task, void *user_data, ThreadStatus status); /* Task handle - opaque pointer */ typedef Task* TaskHandle; /** * Create a new task * @param func The function to execute * @param user_data Data passed to the function * @param priority Task priority level * @return Task handle or NULL on error */ TaskHandle task_create(TaskFunc func, void *user_data, TaskPriority priority); /** * Create a task with completion callback */ TaskHandle task_create_with_callback(TaskFunc func, void *user_data, TaskPriority priority, TaskCallback on_complete, void *callback_data); /** * Destroy a task (only if not submitted) */ void task_destroy(TaskHandle task); /** * Cancel a task (best effort - may already be running) */ bool task_cancel(TaskHandle task); /** * Get current task state */ TaskState task_get_state(TaskHandle task); /** * Wait for task completion (blocking) */ ThreadStatus task_wait(TaskHandle task, uint64_t timeout_ms); /** * Check if task was cancelled */ bool task_is_cancelled(TaskHandle task); /* ============================================================================ * Thread Pool - Manage Worker Threads * ============================================================================ */ /* Thread pool configuration */ typedef struct { uint32_t min_threads; /* Minimum threads to keep alive */ uint32_t max_threads; /* Maximum threads allowed */ uint32_t queue_capacity; /* Task queue capacity per priority */ uint32_t steal_attempts; /* Work stealing attempts before blocking */ uint64_t idle_timeout_ms; /* Time before idle thread terminates */ bool enable_work_stealing; /* Enable work stealing between queues */ } ThreadPoolConfig; /* Default configuration */ #define THREAD_POOL_DEFAULT_CONFIG ((ThreadPoolConfig){ \ .min_threads = 2, \ .max_threads = 8, \ .queue_capacity = 256, \ .steal_attempts = 4, \ .idle_timeout_ms = 60000, \ .enable_work_stealing = true \ }) /** * Create a thread pool */ ThreadPool* thread_pool_create(const ThreadPoolConfig *config); /** * Destroy thread pool, cancelling pending tasks */ void thread_pool_destroy(ThreadPool *pool); /** * Submit a task to the pool */ ThreadStatus thread_pool_submit(ThreadPool *pool, TaskHandle task); /** * Submit a function as a task (convenience) */ ThreadStatus thread_pool_submit_func(ThreadPool *pool, TaskFunc func, void *user_data, TaskPriority priority); /** * Get number of active threads */ uint32_t thread_pool_active_count(ThreadPool *pool); /** * Get number of pending tasks */ uint32_t thread_pool_pending_count(ThreadPool *pool); /** * Shutdown pool gracefully, waiting for tasks to complete */ ThreadStatus thread_pool_shutdown(ThreadPool *pool, uint64_t timeout_ms); /** * Get the default/global thread pool */ ThreadPool* thread_pool_default(void); /** * Initialize the default thread pool */ ThreadStatus thread_pool_init_default(const ThreadPoolConfig *config); /** * Shutdown the default thread pool */ void thread_pool_shutdown_default(void); /* ============================================================================ * Lock-Free Queue - Single Producer Single Consumer * ============================================================================ */ #define SPSC_QUEUE_SIZE 1024 typedef struct { _Atomic uint64_t head CACHE_ALIGN; /* Write index - producer only */ _Atomic uint64_t tail CACHE_ALIGN; /* Read index - consumer only */ void *buffer[SPSC_QUEUE_SIZE]; } SpscQueue; /** * Initialize SPSC queue */ void spsc_queue_init(SpscQueue *q); /** * Push item (producer only) * @return false if queue full */ bool spsc_queue_push(SpscQueue *q, void *item); /** * Pop item (consumer only) * @return false if queue empty */ bool spsc_queue_pop(SpscQueue *q, void **item); /** * Check if queue is empty (consumer only) */ bool spsc_queue_empty(SpscQueue *q); /** * Get approximate size (not synchronized) */ uint64_t spsc_queue_size_approx(SpscQueue *q); /* ============================================================================ * Lock-Free Queue - Multi Producer Single Consumer * ============================================================================ */ typedef struct MpscQueue MpscQueue; /** * Create MPSC queue */ MpscQueue* mpsc_queue_create(uint32_t capacity); /** * Destroy MPSC queue */ void mpsc_queue_destroy(MpscQueue *q); /** * Push item (thread-safe, any producer) * @return false if queue full */ bool mpsc_queue_push(MpscQueue *q, void *item); /** * Pop item (consumer only - single thread) * @return false if queue empty */ bool mpsc_queue_pop(MpscQueue *q, void **item); /** * Check if queue is empty */ bool mpsc_queue_empty(MpscQueue *q); /* ============================================================================ * Channel - Thread-Safe Communication * ============================================================================ */ typedef enum { CHANNEL_UNBUFFERED = 0, /* Synchronous - sender blocks until received */ CHANNEL_BUFFERED = 1 /* Asynchronous - uses internal buffer */ } ChannelType; /** * Create a channel * @param capacity Buffer size (0 for unbuffered synchronous channel) */ Channel* channel_create(uint32_t capacity); /** * Destroy channel */ void channel_destroy(Channel *ch); /** * Send data through channel (blocking) * @return THREAD_OK on success, THREAD_ERROR_CLOSED if closed */ ThreadStatus channel_send(Channel *ch, void *data); /** * Send with timeout */ ThreadStatus channel_send_timeout(Channel *ch, void *data, uint64_t timeout_ms); /** * Try send (non-blocking) */ ThreadStatus channel_try_send(Channel *ch, void *data); /** * Receive from channel (blocking) */ ThreadStatus channel_recv(Channel *ch, void **data); /** * Receive with timeout */ ThreadStatus channel_recv_timeout(Channel *ch, void **data, uint64_t timeout_ms); /** * Try receive (non-blocking) */ ThreadStatus channel_try_recv(Channel *ch, void **data); /** * Close channel (no more sends allowed) */ void channel_close(Channel *ch); /** * Check if channel is closed */ bool channel_is_closed(Channel *ch); /** * Select on multiple channels (like Go's select) * Returns index of ready channel or -1 on timeout */ int channel_select(Channel **channels, uint32_t count, uint64_t timeout_ms, void **out_data); /* ============================================================================ * Future/Promise - Async Result Handling * ============================================================================ */ typedef void* FutureResult; typedef void (*FutureCallback)(Future *f, FutureResult result, void *user_data); /** * Create a future */ Future* future_create(void); /** * Destroy future */ void future_destroy(Future *f); /** * Set the result (called by producer) */ void future_set_result(Future *f, FutureResult result); /** * Set error result */ void future_set_error(Future *f, int error_code); /** * Get result (blocking) */ FutureResult future_get(Future *f, ThreadStatus *status); /** * Get result with timeout */ FutureResult future_get_timeout(Future *f, uint64_t timeout_ms, ThreadStatus *status); /** * Check if future is ready */ bool future_is_ready(Future *f); /** * Attach callback to be called when ready (thread-safe) */ void future_then(Future *f, FutureCallback callback, void *user_data); /** * Create future that completes when all given futures complete */ Future* future_all(Future **futures, uint32_t count); /** * Create future that completes when any given future completes */ Future* future_any(Future **futures, uint32_t count); /* ============================================================================ * Event Bus - Thread-Safe Pub/Sub * ============================================================================ */ typedef uint32_t EventType; typedef uint32_t SubscriptionId; /* Event handler signature */ typedef void (*EventHandler)(EventType type, void *event_data, void *user_data); /* Event filter - return true to allow event */ typedef bool (*EventFilter)(EventType type, void *event_data, void *user_data); /** * Create event bus */ EventBus* event_bus_create(void); /** * Destroy event bus */ void event_bus_destroy(EventBus *bus); /** * Subscribe to event type * @return Subscription ID or 0 on error */ SubscriptionId event_bus_subscribe(EventBus *bus, EventType type, EventHandler handler, void *user_data); /** * Subscribe with filter */ SubscriptionId event_bus_subscribe_filtered(EventBus *bus, EventType type, EventHandler handler, void *user_data, EventFilter filter, void *filter_data); /** * Unsubscribe */ bool event_bus_unsubscribe(EventBus *bus, SubscriptionId id); /** * Publish event (thread-safe) */ void event_bus_publish(EventBus *bus, EventType type, void *event_data); /** * Publish event with custom free function */ void event_bus_publish_owned(EventBus *bus, EventType type, void *event_data, void (*free_fn)(void*)); /** * Process pending events (call from main thread) * @return number of events processed */ uint32_t event_bus_process(EventBus *bus); /** * Set processing limit per call */ void event_bus_set_batch_size(EventBus *bus, uint32_t batch_size); /** * Get the global/default event bus */ EventBus* event_bus_default(void); /** * Initialize default event bus */ bool event_bus_init_default(void); /** * Shutdown default event bus */ void event_bus_shutdown_default(void); /* ============================================================================ * Async Context - Per-Module Async State * ============================================================================ */ /* Context for managing async operations within a module */ struct AsyncContext { ThreadPool *pool; EventBus *event_bus; Channel *completion_channel; atomic_int operation_count; atomic_int shutdown_requested; pthread_mutex_t mutex; }; /** * Create async context */ AsyncContext* async_context_create(const char *name); /** * Destroy async context (cancels all pending operations) */ void async_context_destroy(AsyncContext *ctx); /** * Submit work to context's thread pool */ TaskHandle async_submit(AsyncContext *ctx, TaskFunc func, void *user_data, TaskPriority priority); /** * Submit work and get future */ Future* async_submit_future(AsyncContext *ctx, TaskFunc func, void *user_data, TaskPriority priority); /** * Check for completed operations (call from main thread) */ uint32_t async_poll(AsyncContext *ctx); /** * Get file descriptor for select() integration * Returns -1 if not available */ int async_get_poll_fd(AsyncContext *ctx); /* ============================================================================ * Timer/Scheduler - Delayed Execution * ============================================================================ */ typedef uint64_t TimerId; typedef void (*TimerCallback)(TimerId id, void *user_data); /** * Schedule one-shot timer */ TimerId timer_schedule(uint64_t delay_ms, TimerCallback callback, void *user_data); /** * Schedule repeating timer */ TimerId timer_schedule_repeating(uint64_t interval_ms, TimerCallback callback, void *user_data); /** * Cancel timer */ bool timer_cancel(TimerId id); /** * Check if timer exists */ bool timer_exists(TimerId id); /** * Process timer events (call from main thread) * @return Number of timers fired */ uint32_t timer_process(void); /** * Get timer file descriptor for select() */ int timer_get_poll_fd(void); /** * Initialize timer subsystem */ bool timer_init(void); /** * Shutdown timer subsystem */ void timer_shutdown(void); /* ============================================================================ * Thread-Local Storage Abstraction * ============================================================================ */ typedef struct TlsKey TlsKey; /** * Create TLS key */ TlsKey* tls_create(void (*destructor)(void*)); /** * Destroy TLS key */ void tls_destroy(TlsKey *key); /** * Set TLS value */ void tls_set(TlsKey *key, void *value); /** * Get TLS value */ void* tls_get(TlsKey *key); /* ============================================================================ * Read-Write Lock Wrapper * ============================================================================ */ typedef struct RwLock RwLock; RwLock* rwlock_create(void); void rwlock_destroy(RwLock *lock); void rwlock_read_lock(RwLock *lock); bool rwlock_read_trylock(RwLock *lock); void rwlock_read_unlock(RwLock *lock); void rwlock_write_lock(RwLock *lock); bool rwlock_write_trylock(RwLock *lock); void rwlock_write_unlock(RwLock *lock); /* ============================================================================ * Barrier and Synchronization * ============================================================================ */ typedef struct Barrier Barrier; Barrier* barrier_create(uint32_t count); void barrier_destroy(Barrier *b); bool barrier_wait(Barrier *b, uint64_t timeout_ms); /* ============================================================================ * Initialization and Cleanup * ============================================================================ */ /** * Initialize entire threading subsystem */ bool threading_init(void); /** * Shutdown entire threading subsystem */ void threading_shutdown(void); /** * Get number of hardware threads */ uint32_t threading_hw_concurrency(void); /** * Current thread ID */ uint64_t threading_current_thread_id(void); /** * Set current thread name (for debugging) */ void threading_set_name(const char *name); /** * Yield current thread */ void threading_yield(void); /* ============================================================================ * Utility Macros * ============================================================================ */ /* Run function in background */ #define ASYNC(func, data) \ thread_pool_submit_func(thread_pool_default(), (func), (data), TASK_PRIORITY_NORMAL) /* Run function with priority */ #define ASYNC_PRIORITY(func, data, prio) \ thread_pool_submit_func(thread_pool_default(), (func), (data), (prio)) /* Create future and submit */ #define ASYNC_FUTURE(ctx, func, data) \ async_submit_future((ctx), (func), (data), TASK_PRIORITY_NORMAL) /* Synchronized block using mutex */ #define WITH_MUTEX(mutex, code) do { \ pthread_mutex_lock(&(mutex)); \ code; \ pthread_mutex_unlock(&(mutex)); \ } while(0) /* Read lock block */ #define WITH_READ_LOCK(rwlock, code) do { \ rwlock_read_lock((rwlock)); \ code; \ rwlock_read_unlock((rwlock)); \ } while(0) /* Write lock block */ #define WITH_WRITE_LOCK(rwlock, code) do { \ rwlock_write_lock((rwlock)); \ code; \ rwlock_write_unlock((rwlock)); \ } while(0) #endif /* DWN_THREADING_H */