Files
sanspie dae4bc19e1 Stage 1: engine core, platform, gpu, vfs
Foundation for the aego engine.

core/    errs, log, handle arena, mathx, clock, stats
platform SDL3 backend plus a headless one, input state, events
gpu      device abstraction with gl33 and null backends
vfs      scheme-based virtual filesystem with overlay mounts
engine   builder, module registry, phase-ordered system loop, jobs
demos    basic, resize, input, headless; sandbox driver

OpenGL bindings are generated into gpu/gl33/gl by tools/gen-gl.sh,
so the module has no external dependencies.
2026-09-18 20:51:54 +03:00

78 lines
1.0 KiB
Go

package engine
import (
"runtime"
"sync"
)
type Jobs struct {
work chan func()
wg sync.WaitGroup
mu sync.Mutex
main []func()
spare []func()
workers int
stopped bool
}
func newJobs(workers int) *Jobs {
if workers <= 0 {
workers = runtime.GOMAXPROCS(0) - 1
}
if workers < 1 {
workers = 1
}
j := &Jobs{
work: make(chan func(), 1024),
main: make([]func(), 0, 64),
spare: make([]func(), 0, 64),
workers: workers,
}
for i := 0; i < workers; i++ {
j.wg.Go(j.loop)
}
return j
}
func (j *Jobs) loop() {
for fn := range j.work {
fn()
}
}
func (j *Jobs) Workers() int {
return j.workers
}
func (j *Jobs) Submit(fn func()) {
j.work <- fn
}
func (j *Jobs) OnMain(fn func()) {
j.mu.Lock()
j.main = append(j.main, fn)
j.mu.Unlock()
}
func (j *Jobs) drain() {
j.mu.Lock()
run := j.main
j.main = j.spare[:0]
j.mu.Unlock()
for i, fn := range run {
fn()
run[i] = nil
}
j.spare = run[:0]
}
func (j *Jobs) stop() {
if j.stopped {
return
}
j.stopped = true
close(j.work)
j.wg.Wait()
j.drain()
}