[英]iOS Swift - Question about semaphores and sequencing in Bluetooth Low Energy Manager
我以开源 Bluefruit 代码为例,特别是 BleManager class,它是与 CBCentralManager 的接口。 我给作者发了邮件,他们没有回复:
看起来 class 是在 singleton 架构中设计的(第 23 行的“共享”),因此当代码中的其他地方调用第一个“BleManager.connect()”时,它是惰性构造的。
令我困惑的是在 init() 中,有一个信号量“等待”function:
override init() {
super.init()
centralManagerPoweredOnSemaphore.wait()
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.global(qos: .background), options: [:])
// centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main, options: [:])
}
我真的只习惯于 DispatchQueue.async() 线程中的信号量。 这不是在主线程上调用 wait() function 吗? 这样不会封号吗? 将取消阻止 that.wait() 调用的 The.signal() 调用位于第 289 行:
extension BleManager: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
DLog("centralManagerDidUpdateState: \(central.state.rawValue)")
// Unlock state lock if we have a known state
if central.state == .poweredOn || central.state == .poweredOff || central.state == .unsupported || central.state == .unauthorized {
centralManagerPoweredOnSemaphore.signal()
}
因此,一旦系统 centralManager 更新了 BLE 实用程序 state,它就会被调用,只要它不是未知的,.signal() 就会被调用,init() 的 rest 就会运行。 我已经使用 print 语句来确认它是如何工作的。 centralManagerPoweredOnSemaphore.wait()被调用,然后是centralManagerDidUpdateState(),然后是init()的rest。 我仍然不明白这一点:
虽然最后它起作用了,但我只是想知道事情的确切顺序实际上是如何在引擎盖下运行以使其正常运行的。
他们使用信号量来阻止对BleManager
object 的任何操作,直到中央退出.unknown
state。
信号量创建时的初始值为init
中的wait
会将其递减为 0,而不是阻塞。 然后初始化中央,并在某个时候输入开机 state。 此时signal
会将信号量返回到 1。
现在看看其他函数,例如connect
function(第 167 行),您会看到它们做的第一件事是wait
,然后向signal
量发出信号。 考虑在两种不同的状态下会发生什么:
.poweredOn
state - 信号量计数为 0,因此wait
块。 假设 BLE state 在某个时候变为.poweredOn
, wait
将结束,信号量立即释放,然后connect
function 继续。.poweredOn
state - 信号量计数为 1,因此wait
不会阻塞,然后立即释放信号量并继续connect
function。其他功能以类似的方式工作。
这种方式的好处是调用代码不需要一直检查state; 它可以访问sharedInstance
,然后立即调用startScan
,而无需检查 Central 是否已打开。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.