#+private package package fjord import "base:runtime" import "core:net" import "core:sync" WorkQueue :: struct { items: [dynamic]net.TCP_Socket, capacity: int, mutex: sync.Mutex, not_empty: sync.Cond, shutdown: bool, allocator: runtime.Allocator, } work_queue_init :: proc( work_queue: ^WorkQueue, capacity: int, allocator := context.allocator, ) { work_queue^ = { items = make([dynamic]net.TCP_Socket, 0, capacity, allocator), capacity = capacity, shutdown = false, allocator = allocator, } } work_queue_destroy :: proc(work_queue: ^WorkQueue) { sync.mutex_lock(&work_queue.mutex) for socket in work_queue.items { net.close(socket) } sync.mutex_unlock(&work_queue.mutex) delete(work_queue.items) } work_queue_enqueue :: proc(work_queue: ^WorkQueue, socket: net.TCP_Socket) -> bool { sync.mutex_lock(&work_queue.mutex) defer sync.mutex_unlock(&work_queue.mutex) if work_queue.shutdown do return false if len(work_queue.items) >= work_queue.capacity { return false } append(&work_queue.items, socket) sync.cond_signal(&work_queue.not_empty) return true } work_queue_dequeue :: proc(work_queue: ^WorkQueue) -> (socket: net.TCP_Socket, ok: bool) { sync.mutex_lock(&work_queue.mutex) defer sync.mutex_unlock(&work_queue.mutex) for len(work_queue.items) == 0 && !work_queue.shutdown { sync.cond_wait(&work_queue.not_empty, &work_queue.mutex) } if work_queue.shutdown && len(work_queue.items) == 0 { return socket, false } socket = pop_front(&work_queue.items) return socket, true } work_queue_shutdown :: proc(work_queue: ^WorkQueue) { sync.mutex_lock(&work_queue.mutex) defer sync.mutex_unlock(&work_queue.mutex) work_queue.shutdown = true sync.cond_broadcast(&work_queue.not_empty) }