Add threading support to LoadableResource
.
This commit is contained in:
parent
e748831f3a
commit
78cafe6566
|
@ -58,12 +58,14 @@ type LoadableResource* = ref object of RootObj
|
|||
done_func: proc()
|
||||
cancel_func: proc()
|
||||
str*: proc(): string
|
||||
use_threads: bool
|
||||
result: ref Result # only to be used with loadAll
|
||||
|
||||
proc newLoadableResource*[T: LoadableResource](
|
||||
start: proc(self: LoadableResource),
|
||||
done: proc() = nil,
|
||||
str: proc(): string = nil,
|
||||
use_threads = false,
|
||||
): T =
|
||||
new(result)
|
||||
result.start_func = start
|
||||
|
@ -71,10 +73,28 @@ proc newLoadableResource*[T: LoadableResource](
|
|||
result.str = str
|
||||
if str == nil:
|
||||
result.str = proc(): string = ""
|
||||
result.use_threads = use_threads
|
||||
|
||||
# main -> thread channels
|
||||
var to_start: Channel[LoadableResource]
|
||||
# main <- thread channels
|
||||
var to_return: Channel[(LoadableResource, bool, string, pointer, int)]
|
||||
var to_done: Channel[LoadableResource]
|
||||
|
||||
proc start*[T: LoadableResource](self: T) =
|
||||
self.status = Started
|
||||
self.start_func(self)
|
||||
if self.use_threads:
|
||||
to_start.send self
|
||||
else:
|
||||
self.start_func(self)
|
||||
|
||||
proc doneImpl*[T: LoadableResource](self: T) =
|
||||
if self.status == Started:
|
||||
self.cancel()
|
||||
else:
|
||||
self.status = NotStarted
|
||||
if self.done_func != nil:
|
||||
self.done_func()
|
||||
|
||||
proc `onload=`*[T: LoadableResource](self: T, onload_func: proc(ok: bool, err: string, p: pointer, len: int)) =
|
||||
self.onload_func = onload_func
|
||||
|
@ -85,25 +105,24 @@ proc onload*[T: LoadableResource](self: T, ok: bool, err: string, p: pointer, le
|
|||
if self.result != nil:
|
||||
self.result[] = (ok, err, p, len)
|
||||
if self.onload_func != nil:
|
||||
self.onload_func(ok, err, p, len)
|
||||
if self.use_threads:
|
||||
to_return.send((self.LoadableResource, ok, err, p, len))
|
||||
else:
|
||||
self.onload_func(ok, err, p, len)
|
||||
else: # cancelled
|
||||
self.status = NotStarted
|
||||
if self.done_func != nil:
|
||||
self.done_func()
|
||||
self.doneImpl()
|
||||
|
||||
# TODO: check if we can always use destructors instead of calling this
|
||||
proc done*[T: LoadableResource](self: T) =
|
||||
if self.status == Started:
|
||||
self.cancel()
|
||||
if self.use_threads:
|
||||
to_done.send self
|
||||
else:
|
||||
self.status = NotStarted
|
||||
if self.done_func != nil:
|
||||
self.done_func()
|
||||
self.doneImpl()
|
||||
|
||||
proc cancel*[T: LoadableResource](self: T) =
|
||||
if self.status != Started:
|
||||
return
|
||||
if self.cancel_func != nil:
|
||||
if self.cancel_func == nil:
|
||||
# self.`onload=`(proc(ok, err, p, len: auto) =
|
||||
# self.done())
|
||||
self.onload_func = proc(ok: bool, err: string, p: pointer, len: int) =
|
||||
|
@ -128,6 +147,31 @@ proc cancel*[T: LoadableResource](self: T) =
|
|||
# results.add res.result[]
|
||||
# res.result = nil
|
||||
|
||||
var worker: Thread[void]
|
||||
proc workerThreadProc() {.thread.} =
|
||||
while true:
|
||||
let res = to_start.recv()
|
||||
if res == nil:
|
||||
break
|
||||
cast[proc(self: LoadableResource) {.gcsafe.}](res.start_func)(res)
|
||||
|
||||
worker.createThread(workerThreadProc)
|
||||
to_start.open()
|
||||
to_return.open()
|
||||
to_done.open()
|
||||
|
||||
proc updateLoadableWorkerThreads*() =
|
||||
while true:
|
||||
let tried = to_return.tryRecv()
|
||||
if not tried.dataAvailable:
|
||||
break
|
||||
let (res, ok, err, p, len) = tried.msg
|
||||
res.onload_func(ok, err, p, len)
|
||||
while true:
|
||||
let tried = to_done.tryRecv()
|
||||
if not tried.dataAvailable:
|
||||
break
|
||||
tried.msg.done_func()
|
||||
|
||||
type Fetch* = ref object of LoadableResource
|
||||
custom: pointer
|
||||
|
@ -226,6 +270,7 @@ proc loadUri*(
|
|||
var done_func: proc()
|
||||
var self: Fetch
|
||||
var uri = uri
|
||||
var use_threads = false
|
||||
when not defined(onlyLocalFiles):
|
||||
when defined(emscripten):
|
||||
const is_remote = true
|
||||
|
@ -261,6 +306,7 @@ proc loadUri*(
|
|||
discard emscripten_fetch_close(cast[ptr emscripten_fetch_t](self.custom))
|
||||
self.custom = nil
|
||||
else:
|
||||
use_threads = true
|
||||
var client = newHttpClient()
|
||||
var response: string
|
||||
start_func = proc(self: LoadableResource) =
|
||||
|
@ -298,7 +344,7 @@ proc loadUri*(
|
|||
if cast[Fetch](self).auto_done:
|
||||
self.done()
|
||||
proc str(): string = uri
|
||||
self = newLoadableResource[Fetch](start_func, done_func, str)
|
||||
self = newLoadableResource[Fetch](start_func, done_func, str, use_threads=use_threads)
|
||||
self.onload_func = onload_func
|
||||
self.auto_done = auto_done
|
||||
if auto_start:
|
||||
|
|
|
@ -77,6 +77,7 @@ import ./screen
|
|||
import ./platform/platform
|
||||
import ./loaders/blend
|
||||
import ./util
|
||||
from loadable import updateLoadableWorkerThreads
|
||||
import arr_ref
|
||||
|
||||
export arr_ref
|
||||
|
@ -165,6 +166,7 @@ proc myou_main_loop*(self: MyouEngine) =
|
|||
##
|
||||
## You usually don't need to call this. Use `run <#run,MyouEngine>`_
|
||||
## instead.
|
||||
updateLoadableWorkerThreads()
|
||||
# TODO: make a table object that can be iterated while changing, e.g. with a
|
||||
# seq and a dirty flag to update the seq
|
||||
if self.new_scenes.len != 0:
|
||||
|
|
Loading…
Reference in a new issue