diff options
author | bptato <nincsnevem662@gmail.com> | 2024-09-29 14:55:23 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-09-29 14:58:05 +0200 |
commit | 3b7ca109b9009d5875f8cc1bd8c8212fd9abc296 (patch) | |
tree | 52f707872c782c49fa442e7e7d989c7748d5821b | |
parent | 0035e58925ef005cca0ea0017ce3d54dfca1e72a (diff) | |
download | chawan-3b7ca109b9009d5875f8cc1bd8c8212fd9abc296.tar.gz |
promise: move PromiseMap to buffer
It's only used there, and there's no reason for every single promise to carry two pointers to support it.
-rw-r--r-- | src/io/promise.nim | 50 | ||||
-rw-r--r-- | src/server/buffer.nim | 73 |
2 files changed, 51 insertions, 72 deletions
diff --git a/src/io/promise.nim b/src/io/promise.nim index 8fb55a9b..efb5a0a0 100644 --- a/src/io/promise.nim +++ b/src/io/promise.nim @@ -14,38 +14,14 @@ type EmptyPromise* = ref object of RootObj cb: (proc()) next: EmptyPromise - opaque: pointer state*: PromiseState Promise*[T] = ref object of EmptyPromise - res: T - get: GetValueProc[T] - - GetValueProc[T] = (proc(opaque: pointer; res: var T)) - - PromiseMap* = object - tab: Table[int, EmptyPromise] - opaque*: pointer + res*: T proc newPromise*[T](): Promise[T] = return Promise[T]() -proc newPromiseMap*(opaque: pointer): PromiseMap = - return PromiseMap( - opaque: opaque - ) - -proc addPromise*[T](map: var PromiseMap; id: int; get: GetValueProc[T]): - Promise[T] = - let promise = Promise[T](get: get, opaque: map.opaque) - map.tab[id] = promise - return promise - -proc addEmptyPromise*(map: var PromiseMap; id: int): EmptyPromise = - let promise = EmptyPromise(opaque: map.opaque) - map.tab[id] = promise - return promise - proc resolve*(promise: EmptyPromise) = var promise = promise while true: @@ -59,17 +35,9 @@ proc resolve*(promise: EmptyPromise) = promise.next = nil proc resolve*[T](promise: Promise[T]; res: T) = - if promise.get != nil: - promise.get(promise.opaque, promise.res) - promise.get = nil promise.res = res promise.resolve() -proc resolve*(map: var PromiseMap; promiseid: int) = - var promise: EmptyPromise - if map.tab.pop(promiseid, promise): - promise.resolve() - proc newResolvedPromise*(): EmptyPromise = let res = EmptyPromise() res.resolve() @@ -80,9 +48,6 @@ proc newResolvedPromise*[T](x: T): Promise[T] = res.resolve(x) return res -func empty*(map: PromiseMap): bool = - map.tab.len == 0 - proc then*(promise: EmptyPromise; cb: (proc())): EmptyPromise {.discardable.} = promise.cb = cb promise.next = EmptyPromise() @@ -104,11 +69,7 @@ proc then*(promise: EmptyPromise; cb: (proc(): EmptyPromise)): EmptyPromise proc then*[T](promise: Promise[T]; cb: (proc(x: T))): EmptyPromise {.discardable.} = - return promise.then(proc() = - if promise.get != nil: - promise.get(promise.opaque, promise.res) - promise.get = nil - cb(promise.res)) + return promise.then(proc() = cb(promise.res)) proc then*[T](promise: EmptyPromise; cb: (proc(): Promise[T])): Promise[T] {.discardable.} = @@ -189,8 +150,8 @@ proc all*(promises: seq[EmptyPromise]): EmptyPromise = res.resolve() return res -# * Promise is converted to a JS promise which will be resolved when the Nim -# promise is resolved. +# Promise is converted to a JS promise which will be resolved when the Nim +# promise is resolved. proc promiseThenCallback(ctx: JSContext; this_val: JSValue; argc: cint; argv: ptr UncheckedArray[JSValue]; magic: cint; @@ -279,8 +240,7 @@ proc toJS*[T, E](ctx: JSContext; promise: Promise[Result[T, E]]): JSValue = JS_UNDEFINED else: toJS(ctx, x.error) - let res = JS_Call(ctx, resolvingFuncs[1], JS_UNDEFINED, 1, - x.toJSValueArray()) + let res = JS_Call(ctx, resolvingFuncs[1], JS_UNDEFINED, 1, x.toJSValueArray()) JS_FreeValue(ctx, res) JS_FreeValue(ctx, x) JS_FreeValue(ctx, resolvingFuncs[0]) diff --git a/src/server/buffer.nim b/src/server/buffer.nim index 858a737c..c50f5653 100644 --- a/src/server/buffer.nim +++ b/src/server/buffer.nim @@ -115,15 +115,11 @@ type userstyle: CSSStylesheet window: Window - InterfaceOpaque = ref object - stream: SocketStream - len: int - auxLen: int - BufferInterface* = ref object - map: PromiseMap + map: seq[tuple[promiseid: int; p: EmptyPromise; get: GetValueProc]] packetid: int - opaque: InterfaceOpaque + len: int + auxLen: int stream*: BufStream BufferConfig* = object @@ -139,20 +135,44 @@ type autofocus*: bool metaRefresh*: MetaRefresh -proc getFromOpaque[T](opaque: pointer; res: var T) = - let opaque = cast[InterfaceOpaque](opaque) - if opaque.len != 0: - var r = opaque.stream.initReader(opaque.len, opaque.auxLen) - r.sread(res) - opaque.len = 0 + GetValueProc = proc(iface: BufferInterface; promise: EmptyPromise) {.nimcall.} + +proc getFromStream[T](iface: BufferInterface; promise: EmptyPromise) = + if iface.len != 0: + let promise = Promise[T](promise) + var r = iface.stream.initReader(iface.len, iface.auxLen) + r.sread(promise.res) + iface.len = 0 + +proc addPromise*[T](iface: BufferInterface; id: int): Promise[T] = + let promise = Promise[T]() + iface.map.add((id, promise, getFromStream[T])) + return promise + +proc addEmptyPromise*(iface: BufferInterface; id: int): EmptyPromise = + let promise = EmptyPromise() + iface.map.add((id, promise, nil)) + return promise + +func findPromise(iface: BufferInterface; promiseid: int): int = + for i in 0 ..< iface.map.len: + if iface.map[i].promiseid == promiseid: + return i + return -1 + +proc resolve(iface: BufferInterface; promiseid: int) = + let i = iface.findPromise(promiseid) + if i != -1: + let (_, promise, get) = iface.map[i] + if get != nil: + get(iface, promise) + promise.resolve() + iface.map.del(i) proc newBufferInterface*(stream: SocketStream; registerFun: proc(fd: int)): BufferInterface = - let opaque = InterfaceOpaque(stream: stream) return BufferInterface( - map: newPromiseMap(cast[pointer](opaque)), packetid: 1, # ids below 1 are invalid - opaque: opaque, stream: newBufStream(stream, registerFun) ) @@ -172,17 +192,17 @@ proc cloneInterface*(stream: SocketStream; registerFun: proc(fd: int)): return iface proc resolve*(iface: BufferInterface; packetid, len, auxLen: int) = - iface.opaque.len = len - iface.opaque.auxLen = auxLen - iface.map.resolve(packetid) + iface.len = len + iface.auxLen = auxLen + iface.resolve(packetid) # Protection against accidentally not exhausting data available to read, - # by setting opaque len to 0 in getFromOpaque. + # by setting len to 0 in getFromStream. # (If this assertion is failing, then it means you then()'ed a promise which # should read something from the stream with an empty function.) - assert iface.opaque.len == 0 + assert iface.len == 0 proc hasPromises*(iface: BufferInterface): bool = - return not iface.map.empty() + return iface.map.len > 0 # get enum identifier of proxy function func getFunId(fun: NimNode): string = @@ -199,18 +219,17 @@ proc buildInterfaceProc(fun: NimNode; funid: string): let nup = ident(funid) # add this to enums let this2 = newIdentDefs(ident("iface"), ident("BufferInterface")) let thisval = this2[0] - var params2: seq[NimNode] + var params2: seq[NimNode] = @[] var retval2: NimNode var addfun: NimNode if retval.kind == nnkEmpty: addfun = quote do: - `thisval`.map.addEmptyPromise(`thisval`.packetid) + `thisval`.addEmptyPromise(`thisval`.packetid) retval2 = ident("EmptyPromise") else: addfun = quote do: - addPromise[`retval`](`thisval`.map, `thisval`.packetid, - getFromOpaque[`retval`]) - retval2 = newNimNode(nnkBracketExpr).add(ident"Promise", retval) + addPromise[`retval`](`thisval`, `thisval`.packetid) + retval2 = newNimNode(nnkBracketExpr).add(ident("Promise"), retval) params2.add(retval2) params2.add(this2) # flatten args |