gpt4 book ai didi

ios - 从 Swift 同步调用到基于 C 的线程不安全库

转载 作者:行者123 更新时间:2023-11-28 06:07:50 28 4
gpt4 key购买 nike

我的 Swift 代码需要调用一些非线程安全的 C 函数。所有调用都需要:

1) 同步(顺序调用函数,仅在前一个调用返回后),

2) 在同一个线程上。

我尝试创建一个队列,然后从一个函数中访问 C:

let queue = DispatchQueue(label: "com.example.app.thread-1", qos: .userInitiated)

func calc(...) -> Double {
var result: Double!
queue.sync {
result = c_func(...)
}
return result
}

这改进了行为,但我仍然遇到崩溃 - 有时,不像以前那么频繁,主要是在从 Xcode 调试时。关于更好处理的任何想法?

编辑

根据下面的评论,有人可以给出一个通用示例,说明如何使用线程类来确保在同一线程上顺序执行吗?

编辑2

在 C 库周围使用这个包装器时,可以看到一个很好的问题示例: https://github.com/PerfectlySoft/Perfect-PostgreSQL

从单个队列访问时它工作正常。但如果涉及多个调度队列,将开始产生奇怪的错误。

所以我设想了一种单一执行线程的方法,当它被调用时,会阻塞调用者,执行计算,解除阻塞调用者并返回结果。对每个连续的调用者重复。

像这样:

thread 1     |              |
---------> | | ---->
thread 2 | executor | ---->
---------> | thread |
thread 3 | -----------> |
---------> | | ---->
...

最佳答案

如果您真的需要确保所有 API 调用必须来自单个线程,您可以使用 Thread 来实现类加 some synchronization primitives .

例如,下面的 SingleThreadExecutor 类提供了这种想法的一种比较直接的实现:

class SingleThreadExecutor {

private var thread: Thread!
private let threadAvailability = DispatchSemaphore(value: 1)

private var nextBlock: (() -> Void)?
private let nextBlockPending = DispatchSemaphore(value: 0)
private let nextBlockDone = DispatchSemaphore(value: 0)

init(label: String) {
thread = Thread(block: self.run)
thread.name = label
thread.start()
}

func sync(block: @escaping () -> Void) {
threadAvailability.wait()

nextBlock = block
nextBlockPending.signal()
nextBlockDone.wait()
nextBlock = nil

threadAvailability.signal()
}

private func run() {
while true {
nextBlockPending.wait()
nextBlock!()
nextBlockDone.signal()
}
}
}

确保指定的 block 确实由单个线程调用的简单测试:

let executor = SingleThreadExecutor(label: "single thread test")
for i in 0..<10 {
DispatchQueue.global().async {
executor.sync { print("\(i) @ \(Thread.current.name!)") }
}
}
Thread.sleep(forTimeInterval: 5) /* Wait for calls to finish. */
0 @ single thread test
1 @ single thread test
2 @ single thread test
3 @ single thread test
4 @ single thread test
5 @ single thread test
6 @ single thread test
7 @ single thread test
8 @ single thread test
9 @ single thread test

最后,将代码中的 DispatchQueue 替换为 SingleThreadExecutor,希望这能解决您的问题 — 非常奇特! — 问题 ;)

let singleThreadExecutor = SingleThreadExecutor(label: "com.example.app.thread-1")

func calc(...) -> Double {
var result: Double!
singleThreadExecutor.sync {
result = c_func(...)
}
return result
}

关于ios - 从 Swift 同步调用到基于 C 的线程不安全库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47724198/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com