/*
 * DWN - Desktop Window Manager
 * retoor <retoor@molodetz.nl>
 * Extensive Abstract Threading Framework - Implementation
 */

#define _GNU_SOURCE
#include "threading.h"
#include "util.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/eventfd.h>
#include <sys/timerfd.h>
#include <time.h>
#include <poll.h>

/* Use C11 atomic operations from stdatomic.h - no custom defines needed */

/* Linux-specific for gettid */
#ifndef SYS_gettid
#define SYS_gettid __NR_gettid
#endif

/* ============================================================================
 * Task Implementation
 * ============================================================================ */

struct Task {
    TaskFunc func;
    void *user_data;
    TaskCallback on_complete;
    void *callback_data;
    TaskPriority priority;
    _Atomic TaskState state;
    _Atomic int cancelled;
    Future *future;              /* Optional associated future */
    ThreadStatus result_status;
    pthread_mutex_t mutex;
    pthread_cond_t completed;
};

TaskHandle task_create(TaskFunc func, void *user_data, TaskPriority priority)
{
    if (!func) return NULL;
    
    Task *task = dwn_malloc(sizeof(Task));
    if (!task) return NULL;
    
    task->func = func;
    task->user_data = user_data;
    task->on_complete = NULL;
    task->callback_data = NULL;
    task->priority = priority;
    atomic_store_explicit(&task->state, TASK_STATE_PENDING, ATOMIC_RELEASE);
    atomic_store_explicit(&task->cancelled, 0, ATOMIC_RELEASE);
    task->future = NULL;
    task->result_status = THREAD_OK;
    
    if (pthread_mutex_init(&task->mutex, NULL) != 0) {
        dwn_free(task);
        return NULL;
    }
    
    if (pthread_cond_init(&task->completed, NULL) != 0) {
        pthread_mutex_destroy(&task->mutex);
        dwn_free(task);
        return NULL;
    }
    
    return task;
}

TaskHandle task_create_with_callback(TaskFunc func, void *user_data,
                                     TaskPriority priority,
                                     TaskCallback on_complete,
                                     void *callback_data)
{
    Task *task = task_create(func, user_data, priority);
    if (!task) return NULL;
    
    task->on_complete = on_complete;
    task->callback_data = callback_data;
    
    return task;
}

void task_destroy(TaskHandle task)
{
    if (!task) return;
    
    TaskState state = atomic_load_explicit(&task->state, ATOMIC_ACQUIRE);
    if (state == TASK_STATE_RUNNING) {
        /* Can't destroy running task */
        return;
    }
    
    pthread_cond_destroy(&task->completed);
    pthread_mutex_destroy(&task->mutex);
    dwn_free(task);
}

bool task_cancel(TaskHandle task)
{
    if (!task) return false;
    
    atomic_store_explicit(&task->cancelled, 1, ATOMIC_RELEASE);
    
    TaskState state = atomic_load_explicit(&task->state, ATOMIC_ACQUIRE);
    return (state != TASK_STATE_COMPLETED && state != TASK_STATE_ERROR);
}

TaskState task_get_state(TaskHandle task)
{
    if (!task) return TASK_STATE_ERROR;
    return atomic_load_explicit(&task->state, ATOMIC_ACQUIRE);
}

ThreadStatus task_wait(TaskHandle task, uint64_t timeout_ms)
{
    if (!task) return THREAD_ERROR_INVALID;
    
    pthread_mutex_lock(&task->mutex);
    
    TaskState state = atomic_load_explicit(&task->state, ATOMIC_ACQUIRE);
    
    if (state != TASK_STATE_COMPLETED && state != TASK_STATE_ERROR && 
        state != TASK_STATE_CANCELLED) {
        if (timeout_ms == 0) {
            /* Infinite wait */
            pthread_cond_wait(&task->completed, &task->mutex);
        } else {
            struct timespec ts;
            clock_gettime(CLOCK_REALTIME, &ts);
            ts.tv_sec += timeout_ms / 1000;
            ts.tv_nsec += (timeout_ms % 1000) * 1000000;
            if (ts.tv_nsec >= 1000000000) {
                ts.tv_sec++;
                ts.tv_nsec -= 1000000000;
            }
            
            int ret = pthread_cond_timedwait(&task->completed, &task->mutex, &ts);
            if (ret == ETIMEDOUT) {
                pthread_mutex_unlock(&task->mutex);
                return THREAD_ERROR_TIMEOUT;
            }
        }
    }
    
    pthread_mutex_unlock(&task->mutex);
    return task->result_status;
}

bool task_is_cancelled(TaskHandle task)
{
    if (!task) return false;
    return atomic_load_explicit(&task->cancelled, ATOMIC_ACQUIRE) != 0;
}

/* Internal: Execute task in worker thread */
static void task_execute(Task *task)
{
    atomic_store_explicit(&task->state, TASK_STATE_RUNNING, ATOMIC_RELEASE);
    
    /* Execute the actual work */
    task->func(task->user_data, &task->cancelled);
    
    /* Determine final state */
    if (atomic_load_explicit(&task->cancelled, ATOMIC_ACQUIRE)) {
        task->result_status = THREAD_ERROR;
        atomic_store_explicit(&task->state, TASK_STATE_CANCELLED, ATOMIC_RELEASE);
    } else {
        atomic_store_explicit(&task->state, TASK_STATE_COMPLETED, ATOMIC_RELEASE);
    }
    
    /* Signal completion */
    pthread_mutex_lock(&task->mutex);
    pthread_cond_broadcast(&task->completed);
    pthread_mutex_unlock(&task->mutex);
    
    /* Call completion callback if set */
    if (task->on_complete) {
        task->on_complete(task, task->callback_data, task->result_status);
    }
    
    /* Set future result if associated */
    if (task->future) {
        future_set_result(task->future, (void*)(uintptr_t)task->result_status);
    }
}

/* ============================================================================
 * Lock-Free SPSC Queue Implementation
 * ============================================================================ */

void spsc_queue_init(SpscQueue *q)
{
    if (!q) return;
    atomic_store_explicit(&q->head, 0, ATOMIC_RELEASE);
    atomic_store_explicit(&q->tail, 0, ATOMIC_RELEASE);
}

bool spsc_queue_push(SpscQueue *q, void *item)
{
    if (!q || !item) return false;
    
    const uint64_t mask = SPSC_QUEUE_SIZE - 1;
    uint64_t head = atomic_load_explicit(&q->head, ATOMIC_RELAXED);
    uint64_t next = (head + 1) & mask;
    
    /* Check if full */
    if (next == atomic_load_explicit(&q->tail, ATOMIC_ACQUIRE)) {
        return false;
    }
    
    q->buffer[head] = item;
    atomic_store_explicit(&q->head, next, ATOMIC_RELEASE);
    atomic_thread_fence(ATOMIC_RELEASE);
    
    return true;
}

bool spsc_queue_pop(SpscQueue *q, void **item)
{
    if (!q || !item) return false;
    
    uint64_t tail = atomic_load_explicit(&q->tail, ATOMIC_RELAXED);
    
    /* Check if empty */
    if (tail == atomic_load_explicit(&q->head, ATOMIC_ACQUIRE)) {
        return false;
    }
    
    *item = q->buffer[tail];
    atomic_store_explicit(&q->tail, (tail + 1) & (SPSC_QUEUE_SIZE - 1), ATOMIC_RELEASE);
    atomic_thread_fence(ATOMIC_RELEASE);
    
    return true;
}

bool spsc_queue_empty(SpscQueue *q)
{
    if (!q) return true;
    return atomic_load_explicit(&q->head, ATOMIC_ACQUIRE) == 
           atomic_load_explicit(&q->tail, ATOMIC_ACQUIRE);
}

uint64_t spsc_queue_size_approx(SpscQueue *q)
{
    if (!q) return 0;
    uint64_t head = atomic_load_explicit(&q->head, ATOMIC_ACQUIRE);
    uint64_t tail = atomic_load_explicit(&q->tail, ATOMIC_ACQUIRE);
    return (head - tail) & (SPSC_QUEUE_SIZE - 1);
}

/* ============================================================================
 * Lock-Free MPSC Queue Implementation
 * ============================================================================ */

/* Based on Dmitry Vyukov's MPMC queue */
struct MpscQueue {
    struct Cell {
        _Atomic(uintptr_t) sequence;
        void *data;
    } *buffer;
    
    uint32_t capacity;
    uint32_t mask;
    
    CACHE_ALIGN _Atomic(uint64_t) head;  /* Consumer position */
    CACHE_ALIGN _Atomic(uint64_t) tail;  /* Producer position */
};

MpscQueue* mpsc_queue_create(uint32_t capacity)
{
    /* Round up to power of 2 */
    uint32_t cap = 1;
    while (cap < capacity) cap <<= 1;
    
    MpscQueue *q = dwn_malloc(sizeof(MpscQueue));
    if (!q) return NULL;
    
    q->buffer = dwn_malloc(sizeof(struct Cell) * cap);
    if (!q->buffer) {
        dwn_free(q);
        return NULL;
    }
    
    q->capacity = cap;
    q->mask = cap - 1;
    
    for (uint32_t i = 0; i < cap; i++) {
        atomic_store_explicit(&q->buffer[i].sequence, i, ATOMIC_RELEASE);
    }
    
    atomic_store_explicit(&q->head, 0, ATOMIC_RELEASE);
    atomic_store_explicit(&q->tail, 0, ATOMIC_RELEASE);
    
    return q;
}

void mpsc_queue_destroy(MpscQueue *q)
{
    if (!q) return;
    dwn_free(q->buffer);
    dwn_free(q);
}

bool mpsc_queue_push(MpscQueue *q, void *item)
{
    if (!q || !item) return false;
    
    struct Cell *cell;
    uint64_t pos = atomic_load_explicit(&q->tail, ATOMIC_RELAXED);
    
    for (;;) {
        cell = &q->buffer[pos & q->mask];
        uint64_t seq = atomic_load_explicit(&cell->sequence, ATOMIC_ACQUIRE);
        
        if (seq < pos) {
            /* Queue full */
            return false;
        }
        
        if (seq == pos) {
            /* Try to claim this slot */
            if (atomic_compare_exchange_strong_explicit(
                    &q->tail, &pos, pos + 1,
                    ATOMIC_RELAXED, ATOMIC_RELAXED)) {
                break;
            }
            /* Failed, retry */
        } else {
            /* Another thread moved tail, retry */
            pos = atomic_load_explicit(&q->tail, ATOMIC_RELAXED);
        }
    }
    
    cell->data = item;
    atomic_store_explicit(&cell->sequence, pos + 1, ATOMIC_RELEASE);
    
    return true;
}

bool mpsc_queue_pop(MpscQueue *q, void **item)
{
    if (!q || !item) return false;
    
    uint64_t pos = atomic_load_explicit(&q->head, ATOMIC_RELAXED);
    struct Cell *cell = &q->buffer[pos & q->mask];
    
    uint64_t seq = atomic_load_explicit(&cell->sequence, ATOMIC_ACQUIRE);
    
    if (seq < pos + 1) {
        /* Empty */
        return false;
    }
    
    /* Only one consumer, no CAS needed */
    atomic_store_explicit(&q->head, pos + 1, ATOMIC_RELAXED);
    
    *item = cell->data;
    atomic_store_explicit(&cell->sequence, pos + q->mask + 1, ATOMIC_RELEASE);
    
    return true;
}

bool mpsc_queue_empty(MpscQueue *q)
{
    if (!q) return true;
    uint64_t head = atomic_load_explicit(&q->head, ATOMIC_ACQUIRE);
    uint64_t tail = atomic_load_explicit(&q->tail, ATOMIC_ACQUIRE);
    return head >= tail;
}

/* ============================================================================
 * Thread Pool Implementation
 * ============================================================================ */

/* Per-worker state for work stealing */
typedef struct {
    pthread_t thread;
    SpscQueue local_queue;
    _Atomic int active;
    _Atomic uint64_t tasks_processed;
    uint32_t id;
    ThreadPool *pool;
} PoolWorker;

struct ThreadPool {
    ThreadPoolConfig config;
    
    /* Priority queues (MPSC) */
    MpscQueue *queues[TASK_PRIORITY_COUNT];
    
    /* Worker threads */
    PoolWorker *workers;
    uint32_t worker_count;
    _Atomic uint32_t active_workers;
    
    /* Synchronization */
    pthread_mutex_t mutex;
    pthread_cond_t work_available;
    _Atomic int shutdown;
    _Atomic uint64_t total_tasks;
    _Atomic uint64_t completed_tasks;
    
    /* Event fd for signaling main thread */
    int event_fd;
};

static void* worker_thread_func(void *arg);

ThreadPool* thread_pool_create(const ThreadPoolConfig *config)
{
    ThreadPool *pool = dwn_malloc(sizeof(ThreadPool));
    if (!pool) return NULL;
    
    pool->config = config ? *config : THREAD_POOL_DEFAULT_CONFIG;
    
    /* Create priority queues */
    for (int i = 0; i < TASK_PRIORITY_COUNT; i++) {
        pool->queues[i] = mpsc_queue_create(pool->config.queue_capacity);
        if (!pool->queues[i]) {
            for (int j = 0; j < i; j++) {
                mpsc_queue_destroy(pool->queues[j]);
            }
            dwn_free(pool);
            return NULL;
        }
    }
    
    /* Allocate workers */
    pool->workers = dwn_malloc(sizeof(PoolWorker) * pool->config.max_threads);
    if (!pool->workers) {
        for (int i = 0; i < TASK_PRIORITY_COUNT; i++) {
            mpsc_queue_destroy(pool->queues[i]);
        }
        dwn_free(pool);
        return NULL;
    }
    
    pool->worker_count = 0;
    atomic_store_explicit(&pool->active_workers, 0, ATOMIC_RELEASE);
    atomic_store_explicit(&pool->shutdown, 0, ATOMIC_RELEASE);
    atomic_store_explicit(&pool->total_tasks, 0, ATOMIC_RELEASE);
    atomic_store_explicit(&pool->completed_tasks, 0, ATOMIC_RELEASE);
    
    pthread_mutex_init(&pool->mutex, NULL);
    pthread_cond_init(&pool->work_available, NULL);
    
    /* Event fd for notification */
    pool->event_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    
    /* Start minimum threads */
    for (uint32_t i = 0; i < pool->config.min_threads; i++) {
        PoolWorker *w = &pool->workers[pool->worker_count];
        spsc_queue_init(&w->local_queue);
        w->id = pool->worker_count;
        w->pool = pool;
        atomic_store_explicit(&w->active, 1, ATOMIC_RELEASE);
        atomic_store_explicit(&w->tasks_processed, 0, ATOMIC_RELEASE);
        
        if (pthread_create(&w->thread, NULL, worker_thread_func, w) == 0) {
            pool->worker_count++;
            atomic_fetch_add_explicit(&pool->active_workers, 1, ATOMIC_RELAXED);
        }
    }
    
    return pool;
}

static Task* steal_task(ThreadPool *pool, PoolWorker *thief)
{
    /* Try to steal from other workers' local queues */
    for (uint32_t i = 0; i < pool->config.steal_attempts; i++) {
        uint32_t victim_idx = (thief->id + i + 1) % pool->worker_count;
        PoolWorker *victim = &pool->workers[victim_idx];
        
        if (victim == thief) continue;
        
        void *task;
        if (spsc_queue_pop(&victim->local_queue, &task)) {
            return (Task*)task;
        }
    }
    
    /* Try global priority queues */
    for (int prio = TASK_PRIORITY_CRITICAL; prio < TASK_PRIORITY_COUNT; prio++) {
        void *task;
        if (mpsc_queue_pop(pool->queues[prio], &task)) {
            return (Task*)task;
        }
    }
    
    return NULL;
}

static void* worker_thread_func(void *arg)
{
    PoolWorker *worker = arg;
    ThreadPool *pool = worker->pool;
    
    char name[16];
    snprintf(name, sizeof(name), "dwn-worker-%u", worker->id);
    threading_set_name(name);
    
    while (!atomic_load_explicit(&pool->shutdown, ATOMIC_ACQUIRE)) {
        Task *task = NULL;
        
        /* Try local queue first */
        if (!spsc_queue_pop(&worker->local_queue, (void**)&task)) {
            /* Try to steal */
            task = steal_task(pool, worker);
        }
        
        if (task) {
            atomic_fetch_add_explicit(&worker->tasks_processed, 1, ATOMIC_RELAXED);
            task_execute(task);
            atomic_fetch_add_explicit(&pool->completed_tasks, 1, ATOMIC_RELEASE);
            
            /* Signal completion via eventfd */
            uint64_t one = 1;
            ssize_t w __attribute__((unused)) = write(pool->event_fd, &one, sizeof(one));
        } else {
            /* No work - wait */
            struct timespec ts;
            clock_gettime(CLOCK_REALTIME, &ts);
            ts.tv_nsec += 1000000; /* 1ms */
            if (ts.tv_nsec >= 1000000000) {
                ts.tv_sec++;
                ts.tv_nsec -= 1000000000;
            }
            
            pthread_mutex_lock(&pool->mutex);
            pthread_cond_timedwait(&pool->work_available, &pool->mutex, &ts);
            pthread_mutex_unlock(&pool->mutex);
        }
    }
    
    atomic_fetch_sub_explicit(&pool->active_workers, 1, ATOMIC_RELAXED);
    return NULL;
}

void thread_pool_destroy(ThreadPool *pool)
{
    if (!pool) return;
    
    thread_pool_shutdown(pool, 5000);
    
    for (uint32_t i = 0; i < pool->worker_count; i++) {
        pthread_join(pool->workers[i].thread, NULL);
    }
    
    for (int i = 0; i < TASK_PRIORITY_COUNT; i++) {
        mpsc_queue_destroy(pool->queues[i]);
    }
    
    close(pool->event_fd);
    pthread_cond_destroy(&pool->work_available);
    pthread_mutex_destroy(&pool->mutex);
    dwn_free(pool->workers);
    dwn_free(pool);
}

ThreadStatus thread_pool_submit(ThreadPool *pool, TaskHandle task)
{
    if (!pool || !task) return THREAD_ERROR_INVALID;
    
    if (atomic_load_explicit(&pool->shutdown, ATOMIC_ACQUIRE)) {
        return THREAD_ERROR_CLOSED;
    }
    
    Task *t = (Task*)task;
    TaskPriority prio = t->priority;
    
    /* Try to push to priority queue */
    if (!mpsc_queue_push(pool->queues[prio], t)) {
        return THREAD_ERROR_BUSY;
    }
    
    atomic_fetch_add_explicit(&pool->total_tasks, 1, ATOMIC_RELAXED);
    
    /* Signal workers */
    pthread_cond_broadcast(&pool->work_available);
    
    /* Dynamically scale up if needed */
    uint32_t active = atomic_load_explicit(&pool->active_workers, ATOMIC_ACQUIRE);
    if (active < pool->config.max_threads && active < pool->worker_count + 2) {
        /* Spawn additional thread */
        pthread_mutex_lock(&pool->mutex);
        if (pool->worker_count < pool->config.max_threads) {
            PoolWorker *w = &pool->workers[pool->worker_count];
            spsc_queue_init(&w->local_queue);
            w->id = pool->worker_count;
            w->pool = pool;
            atomic_store_explicit(&w->active, 1, ATOMIC_RELEASE);
            
            if (pthread_create(&w->thread, NULL, worker_thread_func, w) == 0) {
                pool->worker_count++;
                atomic_fetch_add_explicit(&pool->active_workers, 1, ATOMIC_RELAXED);
            }
        }
        pthread_mutex_unlock(&pool->mutex);
    }
    
    return THREAD_OK;
}

ThreadStatus thread_pool_submit_func(ThreadPool *pool, TaskFunc func, 
                                     void *user_data, TaskPriority priority)
{
    TaskHandle task = task_create(func, user_data, priority);
    if (!task) return THREAD_ERROR_NOMEM;
    
    ThreadStatus status = thread_pool_submit(pool, task);
    if (status != THREAD_OK) {
        task_destroy(task);
    }
    return status;
}

uint32_t thread_pool_active_count(ThreadPool *pool)
{
    if (!pool) return 0;
    return atomic_load_explicit(&pool->active_workers, ATOMIC_ACQUIRE);
}

uint32_t thread_pool_pending_count(ThreadPool *pool)
{
    if (!pool) return 0;
    
    uint64_t total = atomic_load_explicit(&pool->total_tasks, ATOMIC_ACQUIRE);
    uint64_t completed = atomic_load_explicit(&pool->completed_tasks, ATOMIC_ACQUIRE);
    
    return (uint32_t)(total - completed);
}

ThreadStatus thread_pool_shutdown(ThreadPool *pool, uint64_t timeout_ms)
{
    (void)timeout_ms;
    if (!pool) return THREAD_ERROR_INVALID;
    
    atomic_store_explicit(&pool->shutdown, 1, ATOMIC_RELEASE);
    pthread_cond_broadcast(&pool->work_available);
    
    /* Cancel pending tasks */
    for (int prio = 0; prio < TASK_PRIORITY_COUNT; prio++) {
        void *task_ptr;
        while (mpsc_queue_pop(pool->queues[prio], &task_ptr)) {
            Task *t = (Task*)task_ptr;
            atomic_store_explicit(&t->state, TASK_STATE_CANCELLED, ATOMIC_RELEASE);
        }
    }
    
    return THREAD_OK;
}

/* ============================================================================
 * Default Thread Pool
 * ============================================================================ */

static ThreadPool *g_default_pool = NULL;

ThreadPool* thread_pool_default(void)
{
    return g_default_pool;
}

ThreadStatus thread_pool_init_default(const ThreadPoolConfig *config)
{
    if (g_default_pool) return THREAD_OK;
    g_default_pool = thread_pool_create(config);
    return g_default_pool ? THREAD_OK : THREAD_ERROR;
}

void thread_pool_shutdown_default(void)
{
    if (g_default_pool) {
        thread_pool_destroy(g_default_pool);
        g_default_pool = NULL;
    }
}

/* ============================================================================
 * Thread-Local Storage
 * ============================================================================ */

struct TlsKey {
    pthread_key_t key;
};

TlsKey* tls_create(void (*destructor)(void*))
{
    TlsKey *k = dwn_malloc(sizeof(TlsKey));
    if (!k) return NULL;
    
    if (pthread_key_create(&k->key, destructor) != 0) {
        dwn_free(k);
        return NULL;
    }
    
    return k;
}

void tls_destroy(TlsKey *key)
{
    if (!key) return;
    pthread_key_delete(key->key);
    dwn_free(key);
}

void tls_set(TlsKey *key, void *value)
{
    if (!key) return;
    pthread_setspecific(key->key, value);
}

void* tls_get(TlsKey *key)
{
    if (!key) return NULL;
    return pthread_getspecific(key->key);
}

/* ============================================================================
 * Read-Write Lock
 * ============================================================================ */

struct RwLock {
    pthread_rwlock_t lock;
};

RwLock* rwlock_create(void)
{
    RwLock *l = dwn_malloc(sizeof(RwLock));
    if (!l) return NULL;
    
    if (pthread_rwlock_init(&l->lock, NULL) != 0) {
        dwn_free(l);
        return NULL;
    }
    
    return l;
}

void rwlock_destroy(RwLock *lock)
{
    if (!lock) return;
    pthread_rwlock_destroy(&lock->lock);
    dwn_free(lock);
}

void rwlock_read_lock(RwLock *lock)
{
    if (!lock) return;
    pthread_rwlock_rdlock(&lock->lock);
}

bool rwlock_read_trylock(RwLock *lock)
{
    if (!lock) return false;
    return pthread_rwlock_tryrdlock(&lock->lock) == 0;
}

void rwlock_read_unlock(RwLock *lock)
{
    if (!lock) return;
    pthread_rwlock_unlock(&lock->lock);
}

void rwlock_write_lock(RwLock *lock)
{
    if (!lock) return;
    pthread_rwlock_wrlock(&lock->lock);
}

bool rwlock_write_trylock(RwLock *lock)
{
    if (!lock) return false;
    return pthread_rwlock_trywrlock(&lock->lock) == 0;
}

void rwlock_write_unlock(RwLock *lock)
{
    if (!lock) return;
    pthread_rwlock_unlock(&lock->lock);
}

/* ============================================================================
 * Barrier
 * ============================================================================ */

struct Barrier {
    pthread_barrier_t barrier;
};

Barrier* barrier_create(uint32_t count)
{
    Barrier *b = dwn_malloc(sizeof(Barrier));
    if (!b) return NULL;
    
    if (pthread_barrier_init(&b->barrier, NULL, count) != 0) {
        dwn_free(b);
        return NULL;
    }
    
    return b;
}

void barrier_destroy(Barrier *b)
{
    if (!b) return;
    pthread_barrier_destroy(&b->barrier);
    dwn_free(b);
}

bool barrier_wait(Barrier *b, uint64_t timeout_ms)
{
    (void)timeout_ms;
    if (!b) return false;
    int ret = pthread_barrier_wait(&b->barrier);
    return (ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD);
}

/* ============================================================================
 * Utility Functions
 * ============================================================================ */

uint32_t threading_hw_concurrency(void)
{
    long nprocs = sysconf(_SC_NPROCESSORS_ONLN);
    return (nprocs > 0) ? (uint32_t)nprocs : 1;
}

uint64_t threading_current_thread_id(void)
{
    return (uint64_t)syscall(SYS_gettid);
}

void threading_set_name(const char *name)
{
    if (!name) return;
    pthread_setname_np(pthread_self(), name);
}

void threading_yield(void)
{
    sched_yield();
}

/* ============================================================================
 * Global Initialization
 * ============================================================================ */

bool threading_init(void)
{
    if (!thread_pool_init_default(NULL)) {
        return false;
    }
    
    if (!timer_init()) {
        thread_pool_shutdown_default();
        return false;
    }
    
    if (!event_bus_init_default()) {
        timer_shutdown();
        thread_pool_shutdown_default();
        return false;
    }
    
    return true;
}

void threading_shutdown(void)
{
    event_bus_shutdown_default();
    timer_shutdown();
    thread_pool_shutdown_default();
}
