Files
text_editor/src/basic/win32_thread.cpp
2025-05-17 08:22:27 +02:00

84 lines
2.7 KiB
C++

int64_t AtomicIncrement(volatile int64_t *i) {
return InterlockedIncrement64(i);
}
int64_t AtomicCompareAndSwap(volatile int64_t *dst, int64_t exchange, int64_t comperand) {
return InterlockedCompareExchange64(dst, exchange, comperand);
}
void PushWork(WorkQueue *wq, void *data, WorkQueueCallback *callback) {
uint32_t new_index = (wq->index_to_write + 1) % Lengthof(wq->entries);
assert(new_index != wq->index_to_read);
WorkQueueEntry *entry = wq->entries + wq->index_to_write;
entry->data = data;
entry->callback = callback;
wq->completion_goal += 1;dex_to_read + 1) % Lengthof(wq->entries);
if (original_index_to_read != wq->index_to_write) {
int64_t index = AtomicCompareAndSwap(&wq->index_to_read, new_index_to_read, original_index_to_read);
if (index == original_index_to_read) {
WorkQueueEntry *entry = wq->entries +
_WriteBarrier();
wq->index_to_write = new_index;
ReleaseSemaphore(wq->semaphore, 1, 0);
}
bool TryDoingWork(WorkQueue *wq) {
bool should_sleep = false;
int64_t original_index_to_read = wq->index_to_read;
int64_t new_index_to_read = (original_inindex;
entry->callback(entry->data);
AtomicIncrement(&wq->completion_index);
}
} else {
should_sleep = true;
}
return should_sleep;
}
DWORD WINAPI WorkQueueThreadEntry(LPVOID param) {
auto ti = (ThreadStartupInfo *)param;
ThreadCtx ctx = {};
ctx.thread_index = ti->thread_index;
InitScratch();
for (;;) {
if (TryDoingWork(ti->queue)) {
WaitForSingleObject(ti->queue->semaphore, INFINITE);
}
}
}
void InitWorkQueue(WorkQueue *queue, uint32_t thread_count, ThreadStartupInfo *info) {
queue->thread_count = thread_count;
queue->index_to_read = 0;
queue->index_to_write = 0;
queue->completion_index = 0;
queue->completion_goal = 0;
queue->semaphore = CreateSemaphoreExA(0, 0, thread_count, 0, 0, SEMAPHORE_ALL_ACCESS);
Assert(queue->semaphore != INVALID_HANDLE_VALUE);
for (uint32_t i = 0; i < thread_count; i++) {
ThreadStartupInfo *ti = info + i;
ti->thread_index = i;
ti->queue = queue;
DWORD thread_id = 0;
HANDLE thread_handle = CreateThread(0, 0, WorkQueueThreadEntry, ti, 0, &thread_id);
Assert(thread_handle != INVALID_HANDLE_VALUE);
ti->thread_id = thread_id;
CloseHandle(thread_handle);
}
}
void WaitUntilCompletion(WorkQueue *wq) {
while (wq->completion_goal != wq->completion_index) {
TryDoingWork(wq);
}
}
bool IsWorkCompleted(WorkQueue *wq) {
bool result = wq->completion_goal == wq->completion_index;
return result;
}