This commit is contained in:
Avently
2025-03-09 02:13:33 +07:00
parent 8a3811c378
commit 3f30137975
2 changed files with 55 additions and 4 deletions
+2 -2
View File
@@ -107,13 +107,13 @@ func chatSendCmdSync(_ cmd: ChatCommand, bgTask: Bool = true, bgDelay: Double? =
}
func chatSendCmd(_ cmd: ChatCommand, bgTask: Bool = true, bgDelay: Double? = nil, _ ctrl: chat_ctrl? = nil, log: Bool = true) async -> ChatResponse {
await withCheckedContinuation { cont in
await withUnsafeContinuation { cont in
cont.resume(returning: chatSendCmdSync(cmd, bgTask: bgTask, bgDelay: bgDelay, ctrl, log: log))
}
}
func chatRecvMsg(_ ctrl: chat_ctrl? = nil) async -> ChatResponse? {
await withCheckedContinuation { cont in
await withUnsafeContinuation { cont in
_ = withBGTask(bgDelay: msgDelay) { () -> ChatResponse? in
let resp = recvSimpleXMsg(ctrl)
cont.resume(returning: resp)
+53 -2
View File
@@ -177,14 +177,65 @@ public func fromCString(_ c: UnsafeMutablePointer<CChar>) -> String {
return s
}
class ThreadExecutor<ResultType> {
private var stackSize: Int
private var qos: QualityOfService
/// Initialize by specifying the stack size
init(stackSize: Int, qos: QualityOfService) {
self.stackSize = stackSize
self.qos = qos
}
/// Execute a closure synchronously on a separate thread and return the result
func executeSync(_ task: @escaping () throws -> ResultType) throws -> ResultType {
// Initialize the semaphore (initially locked)
let semaphore = DispatchSemaphore(value: 0)
var result: Result<ResultType, Error>?
// Initialize the thread
let thread = Thread {
do {
let taskResult = try task()
result = .success(taskResult)
} catch {
result = .failure(error)
}
// Release the semaphore when the task is completed
semaphore.signal()
}
thread.stackSize = stackSize
thread.qualityOfService = qos
thread.start()
// Wait until the thread completes
semaphore.wait()
// Return the result
switch result! {
case .success(let result):
return result
case .failure(let error):
throw error
}
}
}
public func chatResponse(_ s: String) -> ChatResponse {
let d = s.data(using: .utf8)!
// TODO is there a way to do it without copying the data? e.g:
// let p = UnsafeMutableRawPointer.init(mutating: UnsafeRawPointer(cjson))
// let d = Data.init(bytesNoCopy: p, count: strlen(cjson), deallocator: .free)
do {
let r = try jsonDecoder.decode(APIResponse.self, from: d)
return r.resp
let executor = ThreadExecutor<APIResponse>(
stackSize: 2*1024*1024, // 2MiB
qos: Thread.current.qualityOfService // inherit priority
)
return try executor.executeSync {
try jsonDecoder.decode(APIResponse.self, from: d)
}.resp
} catch {
logger.error("chatResponse jsonDecoder.decode error: \(error.localizedDescription)")
}