Musa-Cpp-Lib-V2/lib/Base/Threads.cpp

113 lines
2.4 KiB
C++

// #thread_primitives
#if OS_WINDOWS
struct Condition_Variable {
CONDITION_VARIABLE condition_variable;
};
struct Semaphore {
HANDLE event;
};
struct Mutex {
CRITICAL_SECTION csection;
};
struct OS_Thread {
HANDLE windows_thread;
s32 windows_thread_id;
};
#endif
#define POSIX_THREADS OS_LINUX || OS_MACOS || OS_IOS || OS_ANDROID
#if OS_MACOS
struct Semaphore {
task_t owner;
semaphore_t event = 0;
};
#endif
#if OS_LINUX || OS_ANDROID
struct Semaphore {
sem_t semaphore;
};
#endif
#if OS_IS_UNIX // #posix threads
struct OS_Thread {
pthread_t thread_handle;
Semaphore is_alive;
Semaphore suspended;
b32 is_done;
};
#endif
struct Thread;
// really hacky forward declares.
struct Work_Entry;
struct Worker_Info;
struct Work_List;
struct Thread_Group;
void init(Work_List* list);
void destroy(Work_List* list);
typedef s64 (*Thread_Proc)(Thread* thread);
s64 thread_group_run (Thread* thread);
struct Thread {
Thread_Context* context;
Thread_Proc proc;
void* data;
s64 index;
OS_Thread os_thread;
// Used by Thread_Group
Worker_Info* worker_info;
};
global u32 next_thread_index = 1;
// Thread Group API (Copied from Jonathan Blow's implementation - I did not come up with this.)
struct Work_Entry {
Work_Entry* next;
void* work;
s64 thread_index; // Thread.index for the thread that handled this work
// string logging_name;
f64 issue_time;
s32 work_list_index;
};
struct Work_List {
Semaphore semaphore;
Mutex mutex;
Work_Entry* first;
Work_Entry* last;
s32 count;
};
struct Worker_Info {
Thread thread;
Work_List available;
Work_List completed;
Thread_Group* group;
s32 worker_index;
u8 padding0[44];
// Work steal indices should be on another cache line:
ArrayView<s32> work_steal_indices;
u8 padding1[48];
};
static_assert(sizeof(Worker_Info) % 64 == 0); // This MUST be padded to cache line!
enum class Thread_Continue_Status : s32 {
THREAD_STOP = 0,
THREAD_CONTINUE = 1
};
typedef Thread_Continue_Status (*Thread_Group_Proc)(Thread_Group* group, Thread* thread, void* work);
struct Thread_Group {
void* data;
Thread_Group_Proc proc;
string name;
Allocator allocator; // for allocating work indices
ArrayView<Worker_Info> worker_info; // only alloc'd once with allocator??
s32 next_worker_index;
bool initialized = false;
bool started = false;
bool should_exit = false;
// bool enable_logging;
};