More efficient way on removing callbacks.
This commit is contained in:
parent
6faceb3b8c
commit
c43d572ad6
|
@ -17,6 +17,7 @@ type
|
||||||
AsyncCallback* = object
|
AsyncCallback* = object
|
||||||
function*: CallbackFunc
|
function*: CallbackFunc
|
||||||
udata*: pointer
|
udata*: pointer
|
||||||
|
deleted*: bool
|
||||||
|
|
||||||
# ZAH: This can probably be stored with a cheaper representation
|
# ZAH: This can probably be stored with a cheaper representation
|
||||||
# until the moment it needs to be printed to the screen (e.g. seq[StackTraceEntry])
|
# until the moment it needs to be printed to the screen (e.g. seq[StackTraceEntry])
|
||||||
|
@ -121,14 +122,13 @@ proc checkFinished[T](future: Future[T]) =
|
||||||
err.cause = future
|
err.cause = future
|
||||||
raise err
|
raise err
|
||||||
|
|
||||||
# ZAH: I've seen this code in asyncloop
|
|
||||||
proc call(callbacks: var Deque[AsyncCallback]) =
|
proc call(callbacks: var Deque[AsyncCallback]) =
|
||||||
var count = len(callbacks)
|
var count = len(callbacks)
|
||||||
if count > 0:
|
while count > 0:
|
||||||
while count > 0:
|
var item = callbacks.popFirst()
|
||||||
var item = callbacks.popFirst()
|
if not item.deleted:
|
||||||
callSoon(item.function, item.udata)
|
callSoon(item.function, item.udata)
|
||||||
dec(count)
|
dec(count)
|
||||||
|
|
||||||
proc add(callbacks: var Deque[AsyncCallback], item: AsyncCallback) =
|
proc add(callbacks: var Deque[AsyncCallback], item: AsyncCallback) =
|
||||||
# ZAH: perhaps this is the default behavior with latest Nim (no need for the `len` check)
|
# ZAH: perhaps this is the default behavior with latest Nim (no need for the `len` check)
|
||||||
|
@ -137,23 +137,9 @@ proc add(callbacks: var Deque[AsyncCallback], item: AsyncCallback) =
|
||||||
callbacks.addLast(item)
|
callbacks.addLast(item)
|
||||||
|
|
||||||
proc remove(callbacks: var Deque[AsyncCallback], item: AsyncCallback) =
|
proc remove(callbacks: var Deque[AsyncCallback], item: AsyncCallback) =
|
||||||
if len(callbacks) > 0:
|
for p in callbacks.mitems():
|
||||||
var count = len(callbacks)
|
if p.function == item.function and p.udata == item.udata:
|
||||||
# ZAH: This is not the most efficient way to implement this.
|
p.deleted = true
|
||||||
# When you discover an element suitalbe for removal, you can put the last
|
|
||||||
# element in its place and reduce the length. The problem is that the
|
|
||||||
# order of callbacks will be changed, which is unfortunate.
|
|
||||||
#
|
|
||||||
# Shifting the elements in-place will still be more efficient than the
|
|
||||||
# current copying due to the CPU cache (because otherwise we may end up
|
|
||||||
# touching memory that's residing on a different cache line).
|
|
||||||
#
|
|
||||||
# I recommend implementing this proper remove logic in the Deque type.
|
|
||||||
while count > 0:
|
|
||||||
var p = callbacks.popFirst()
|
|
||||||
if p.function != item.function or p.udata != item.udata:
|
|
||||||
callbacks.addLast(p)
|
|
||||||
dec(count)
|
|
||||||
|
|
||||||
proc complete*[T](future: Future[T], val: T) =
|
proc complete*[T](future: Future[T], val: T) =
|
||||||
## Completes ``future`` with value ``val``.
|
## Completes ``future`` with value ``val``.
|
||||||
|
@ -379,9 +365,6 @@ proc asyncCheckProxy[T](udata: pointer) =
|
||||||
injectStacktrace(future)
|
injectStacktrace(future)
|
||||||
raise future.error
|
raise future.error
|
||||||
|
|
||||||
proc spawnProxy[T](udata: pointer) =
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc asyncCheck*[T](future: Future[T]) =
|
proc asyncCheck*[T](future: Future[T]) =
|
||||||
## Sets a callback on ``future`` which raises an exception if the future
|
## Sets a callback on ``future`` which raises an exception if the future
|
||||||
## finished with an error.
|
## finished with an error.
|
||||||
|
@ -396,11 +379,6 @@ proc asyncCheck*[T](future: Future[T]) =
|
||||||
# injectStacktrace(future)
|
# injectStacktrace(future)
|
||||||
# raise future.error
|
# raise future.error
|
||||||
|
|
||||||
proc spawn*[T](future: Future[T]) =
|
|
||||||
# ZAH: What is the purpose of this?
|
|
||||||
assert(not future.isNil, "Future is nil")
|
|
||||||
future.callback = spawnProxy[T]
|
|
||||||
|
|
||||||
# ZAH: The return type here could be a Future[(T, Y)]
|
# ZAH: The return type here could be a Future[(T, Y)]
|
||||||
proc `and`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
proc `and`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
||||||
## Returns a future which will complete once both ``fut1`` and ``fut2``
|
## Returns a future which will complete once both ``fut1`` and ``fut2``
|
||||||
|
|
Loading…
Reference in New Issue