Skip to content

Instantly share code, notes, and snippets.

@nitely
Last active June 15, 2024 01:19
Show Gist options
  • Save nitely/f2c76b4eda3cc83f7f34b197a8a4e70b to your computer and use it in GitHub Desktop.
Save nitely/f2c76b4eda3cc83f7f34b197a8a4e70b to your computer and use it in GitHub Desktop.
ValueAsync
type
ValueAsync*[T] = ref object
sigPut, sigPop: SignalAsync
val: T
isClosed: bool
func newValueAsync*[T](): ValueAsync[T] =
ValueAsync[T](
sigPut: newSignal(),
sigPop: newSignal(),
val: nil,
isClosed: false
)
proc put*[T](vala: ValueAsync[T], val: T) {.async.} =
if vala.isClosed:
raise newValueAsyncClosedError()
while vala.val != nil:
await vala.sigPut.waitFor()
vala.val = val
vala.sigPop.trigger()
proc pop*[T](vala: ValueAsync[T]): Future[T] {.async.}
if vala.isClosed:
raise newValueAsyncClosedError()
while vala.val == nil:
await vala.sigPop.waitFor()
result = vala.val
vala.val = nil
vala.sigPut.trigger()
proc close*[T](vala: ValueAsync[T]) {.raises: [].} =
if vala.isClosed:
return
vala.isClosed = true
vala.sigPut.close()
vala.sigPop.close()
when isMainModule:
func newIntRef(n: int): ref int =
new result
result[] = n
block:
proc test() {.async.} =
var q = newValueAsync[ref int]()
await q.put newIntRef(1)
doAssert (await q.pop())[] == 1
await q.put newIntRef(2)
doAssert (await q.pop())[] == 2
await q.put newIntRef(3)
doAssert (await q.pop())[] == 3
await q.put newIntRef(4)
doAssert (await q.pop())[] == 4
waitFor test()
doAssert not hasPendingOperations()
block:
proc test() {.async.} =
var q = newValueAsync[ref int]()
proc puts {.async.} =
await q.put newIntRef(1)
await q.put newIntRef(2)
await q.put newIntRef(3)
await q.put newIntRef(4)
let puts1 = puts()
doAssert (await q.pop())[] == 1
doAssert (await q.pop())[] == 2
doAssert (await q.pop())[] == 3
doAssert (await q.pop())[] == 4
await puts1
waitFor test()
doAssert not hasPendingOperations()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment