Mercurial > games > semicongine
changeset 1361:48df70e8aeed
merge
author | sam <sam@basx.dev> |
---|---|
date | Mon, 04 Nov 2024 00:06:30 +0700 |
parents | cc32bc4fddc2 (diff) 49a7d05d3f28 (current diff) |
children | 3dbf77ca78b9 |
files | |
diffstat | 1 files changed, 67 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/background_loader.nim Mon Nov 04 00:06:30 2024 +0700 @@ -0,0 +1,67 @@ +import std/syncio +import std/tables + +type + LoaderThreadArgs[T] = + (ptr Channel[string], ptr Channel[LoaderResponse[T]], proc(f: string): T {.gcsafe.}) + LoaderResponse[T] = object + file: string + data: T + error: string + + BackgroundLoader[T] = object + loadRequestCn: Channel[string] # used for sending load requests + responseCn: Channel[LoaderResponse[T]] # used for sending back loaded data + worker: Thread[LoaderThreadArgs[T]] # does the actual loading from the disk + responseTable: Table[string, LoaderResponse[T]] # stores results + +proc loader[T](args: LoaderThreadArgs[T]) {.thread.} = + while true: + let file = args[0][].recv() + try: + args[1][].send(LoaderResponse[T](file: file, data: args[2](file))) + except Exception as e: + args[1][].send(LoaderResponse[T](file: file, error: e.msg)) + +proc fetchAll*(ld: var BackgroundLoader) = + var (hasData, response) = ld.responseCn.tryRecv() + while hasData: + ld.responseTable[response.file] = response + (hasData, response) = ld.responseCn.tryRecv() + +proc requestLoading*(ld: var BackgroundLoader, file: string) = + ld.loadRequestCn.send(file) + +proc isLoaded*(ld: var BackgroundLoader, file: string): bool = + ld.fetchAll * () + file in ld.responseTable + +proc getLoaded*[T](ld: var BackgroundLoader[T], file: string): T = + var item: LoaderResponse[T] + doAssert ld.responseTable.pop(file, item) + if item.error != "": + raise newException(Exception, item.error) + result = item.data + +proc initBackgroundLoader*[T]( + loadFn: proc(f: string): T {.gcsafe.} +): ptr BackgroundLoader[T] = + result = cast[ptr BackgroundLoader[T]](allocShared0(sizeof(BackgroundLoader[T]))) + open(result.loadRequestCn) + open(result.responseCn) + createThread[LoaderThreadArgs[T]]( + result.worker, + loader[T], + (addr result.loadRequestCn, addr result.responseCn, loadFn), + ) + +# threaded background loaders + +proc rawLoaderFunc(f: string): seq[byte] {.gcsafe.} = + cast[seq[byte]](toSeq(f.readFile())) + +proc audioLoaderFunc(f: string): seq[byte] {.gcsafe.} = + cast[seq[byte]](toSeq(f.readFile())) + +var rawLoader = initBackgroundLoader(rawLoaderFunc) +var rawLoader = initBackgroundLoader(rawLoaderFunc)