-
-
Save dom96/0c73a80b0dba2453956a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type | |
| PacceptAsyncArgObject = ref object of TObject | |
| dummy1: PAsyncSocket | |
| type | |
| PacceptAsyncRetObject* = ref object of TObject | |
| resultVal*: PAsyncSocket | |
| proc acceptAsync*(socket: PAsyncSocket): PPromise | |
| iterator acceptAsync*(arg: PObject): PPromise {.closure.} = | |
| let passedInParams = PacceptAsyncArgObject(arg) | |
| let socket = passedInParams.dummy1 | |
| var readPromise = PPromise(special: true, socket: socket, kind: reqRead, | |
| finished: false) | |
| yield readPromise | |
| var client: PAsyncSocket | |
| new(client) | |
| accept(socket, client) | |
| var retObj = PacceptAsyncRetObject(resultVal: client) | |
| yield PPromise(special: false, finished: true, value: retObj) | |
| proc acceptAsync*(socket: PAsyncSocket): PPromise = | |
| var params: PacceptAsyncArgObject | |
| new(params) | |
| params.dummy1 = socket | |
| result = PPromise(special: false, iter: acceptAsync, arg: params, | |
| finished: false) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| proc acceptAsync*(socket: PAsyncSocket): PAsyncSocket {.async.} = | |
| ## Accepts a client connecting to a server socket asynchronously. | |
| ## Returns that client. | |
| var readPromise = PPromise(special: true, socket: socket, | |
| kind: reqRead, finished: false) | |
| await readPromise | |
| var client: PAsyncSocket; new(client) | |
| accept(socket, client) | |
| return client |
Pseudo-code for type erasure for promises. I took some liberties with the type of "onCompleted":
type
PromiseBase = object
onCompleted: seq[proc()] # should be a event/signal really
Promise[T] = object of PromiseBase
value: T
proc resolve[T](p: var Promise[T], value: T) =
p.value = T
p.onCompleted()
template wrapYield(iter, promise) =
promise.onCompleted do:
if not finished(iter): discard iter()
yield promiseHmm, macro expansion should do something like this:
proc myRead(sock: PAsyncSocket): string {.async.} =
var dataPromise = readAsync(sock)
let data = await dataPromise
return data
iterator myReadIter(s: Socket, caller_result: Promise[string]): PromiseBase =
var promise: Promise[string] = s.asyncRead()
wrapYield (this_iterator, promise)
var data = promise.value
caller_result.resolve(data)
proc myRead(s: Socket): Promise[string] =
result = new(Promise[string])
discard myReadIter(s, result)One little fix. The code above is assuming that closure iterators are defined in a different style.
With the current compiler, it should really be like this:
proc myRead(s: Socket): Promise[string] =
result = new(Promise[string])
var caller_result = result
var myReadIter = iterator(): PRomiseBase =
var promise: Promise[string] = s.asyncRead()
wrapYield (myReadIter, promise)
var data = promise.value
caller_result.resolve(data) # pay attention here!
# any returns in the original proc are translated
# to caller_result.resolve
discard myReadIter()
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You may have the wrong idea that all of the "async" procs should be written as iterators. There is a basic API written as regular procs serving as a toolbox for writing .async. procs. Here is how async accept should look in pseudo-code: