#ifndef COR_PLATFORM_H
#define COR_PLATFORM_H
// platform specific parts collected together
#include <stdbool.h>

#include <pthread.h>
#include <errno.h>

// inspired by CPython to achieve platform indenpendence for thread local variables
#ifdef thread_local
    #define _Cor_thread_local thread_local
#elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
    #define _Cor_thread_local _Thread_local
#elif defined(_MSC_VER)  /* AKA NT_THREADS */
    #define _Cor_thread_local __declspec(thread)
#elif defined(__GNUC__)  /* includes clang */
    #define _Cor_thread_local __thread
#else
    #define _Cor_thread_local
#endif

// Non-reentrant Mutexes
typedef struct _Cor_Mutex {
    pthread_mutex_t mut;
} _Cor_Mutex;

extern void _Cor_Mutex_ctor(_Cor_Mutex *);
extern void _Cor_Mutex_dtor(_Cor_Mutex *);
extern void _Cor_Mutex_Lock(_Cor_Mutex *);
extern void _Cor_Mutex_Unlock(_Cor_Mutex *);

// The 'now' to use for _Cor_Semaphore_Wait, in ns.
extern int64_t _Cor_Realtime_Now();

typedef struct _Cor_Semaphore {
    pthread_mutex_t mut;
    pthread_cond_t cond;
    unsigned count;
} _Cor_Semaphore;

extern void _Cor_Semaphore_ctor(_Cor_Semaphore *sem);
extern void _Cor_Sempahore_dtor(_Cor_Semaphore *sem);

// timeout_when < 0 means 'wait forever'
// Returns true for success, false for timeout
extern bool _Cor_Semaphore_Wait(_Cor_Semaphore *sem, int64_t timeout_when);

extern void _Cor_Semaphore_Signal(_Cor_Semaphore *sem);

typedef struct _Cor_Thread {
    pthread_t th;
    bool joined;
} _Cor_Thread;

extern void _Cor_Thread_ctor(_Cor_Thread *, void *(*)(void *), void *);
extern void _Cor_Thread_dtor(_Cor_Thread *);
extern void *_Cor_Thread_Join(_Cor_Thread *);

#endif
