nim-ffi/ffi/ffi_thread_request.nim

70 lines
2.1 KiB
Nim
Raw Permalink Normal View History

2025-08-16 02:14:29 +02:00
## This file contains the base message request type that will be handled.
## The requests are created by the main thread and processed by
2025-12-11 23:46:05 +01:00
## the FFI Thread.
2025-08-16 02:14:29 +02:00
2025-09-02 23:47:08 +02:00
import std/[json, macros], results, tables
2025-08-16 02:14:29 +02:00
import chronos, chronos/threadsync
import ./ffi_types, ./internal/ffi_macro, ./alloc
2025-08-16 02:14:29 +02:00
type FFIDestroyContentProc* = proc(content: pointer) {.nimcall, gcsafe.}
2025-08-16 02:14:29 +02:00
type FFIThreadRequest* = object
callback: FFICallBack
userData: pointer
reqId*: cstring
2025-08-16 02:14:29 +02:00
reqContent*: pointer
deleteReqContent*: FFIDestroyContentProc
## Called by sendRequestToFFIThread on failure to free reqContent when
## the FFI thread will never process (and thus never free) this request.
2025-08-16 02:14:29 +02:00
proc init*(
T: typedesc[FFIThreadRequest],
callback: FFICallBack,
userData: pointer,
2025-09-02 23:47:08 +02:00
reqId: cstring,
2025-08-16 02:14:29 +02:00
reqContent: pointer,
): ptr type T =
var ret = createShared(FFIThreadRequest)
ret[].callback = callback
ret[].userData = userData
2025-09-02 23:47:08 +02:00
ret[].reqId = reqId.alloc()
2025-08-16 02:14:29 +02:00
ret[].reqContent = reqContent
return ret
proc deleteRequest*(request: ptr FFIThreadRequest) =
if not request[].deleteReqContent.isNil():
request[].deleteReqContent(request[].reqContent)
2025-09-02 23:47:08 +02:00
deallocShared(request[].reqId)
2025-08-16 02:14:29 +02:00
deallocShared(request)
proc handleRes*[T: string | void](
2025-08-16 02:14:29 +02:00
res: Result[T, string], request: ptr FFIThreadRequest
) =
## Handles the Result responses, which can either be Result[string, string] or
## Result[void, string].
defer:
deleteRequest(request)
if res.isErr():
foreignThreadGc:
2025-12-11 23:46:05 +01:00
let msg = "ffi error: handleRes fireSyncRes error: " & $res.error
2025-08-16 02:14:29 +02:00
request[].callback(
RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), request[].userData
)
return
foreignThreadGc:
var resStr: string
## we need to bind the string to extend its lifetime to callback's in ARC/ORC
2025-08-16 02:14:29 +02:00
when T is string:
resStr = res.get()
let msg: cstring = resStr.cstring()
2025-08-16 02:14:29 +02:00
request[].callback(
RET_OK, unsafeAddr msg[0], cast[csize_t](len(msg)), request[].userData
)
return
proc nilProcess*(reqId: cstring): Future[Result[string, string]] {.async.} =
2025-08-16 02:14:29 +02:00
return err("This request type is not implemented: " & $reqId)