繁体   English   中英

iOS Swift - 关于蓝牙低功耗管理器中信号量和排序的问题

[英]iOS Swift - Question about semaphores and sequencing in Bluetooth Low Energy Manager

我以开源 Bluefruit 代码为例,特别是 BleManager class,它是与 CBCentralManager 的接口。 我给作者发了邮件,他们没有回复:

Bluefruit BleManager class

看起来 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。 我仍然不明白这一点:

  • 主线程上的 semaphore.wait() 是如何不锁定所有内容的? 例如,查看第 169 和 170 行。那是做什么的?
  • 尚未分配委托时如何调用 centralManagerDidUpdateState()? 似乎在 function 之前没有立即调用的 init() 底部分配了委托。系统 CBCentralManager 如何知道使用特定的 centralManagerDidUpdateState() function?
  • CBCentralManager 状态究竟是如何工作的? 我已经通读了官方文档,但描述性并不强。 似乎当“核心蓝牙初始化或重置”时它将是“未知” 然后在一段时间后,它是否会始终更改为已知的 state,这取决于设备是否具有该功能以及用户设置/权限是什么? 所以我猜这就是为什么在我们得到响应之前阻止 class 的 rest 是“安全的”。 但是在这种情况下是什么“初始化”了 Core Bluetooth? 据我所知,在部分 init() 和 centralManagerDidUpdateState() 之前,没有调用任何核心蓝牙功能。 是什么让 Core Bluetooth 尝试初始化 BLE 实用程序并更新 state? 看起来这个 BleManager class 被懒惰地调用了,所以它不可能是更高级别的东西。

虽然最后它起作用了,但我只是想知道事情的确切顺序实际上是如何在引擎盖下运行以使其正常运行的。

他们使用信号量来阻止对BleManager object 的任何操作,直到中央退出.unknown state。

信号量创建时的初始值为init中的wait会将其递减为 0,而不是阻塞。 然后初始化中央,并在某个时候输入开机 state。 此时signal会将信号量返回到 1。

现在看看其他函数,例如connect function(第 167 行),您会看到它们做的第一件事是wait ,然后向signal量发出信号。 考虑在两种不同的状态下会发生什么:

  1. 中央尚未在.poweredOn state - 信号量计数为 0,因此wait块。 假设 BLE state 在某个时候变为.poweredOnwait将结束,信号量立即释放,然后connect function 继续。
  2. 中央已经在.poweredOn state - 信号量计数为 1,因此wait不会阻塞,然后立即释放信号量并继续connect function。

其他功能以类似的方式工作。

这种方式的好处是调用代码不需要一直检查state; 它可以访问sharedInstance ,然后立即调用startScan ,而无需检查 Central 是否已打开。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM