0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Incorrect actor executor assumption

Posted at

global actorを用いて実装していたところ上記のエラーが出た。
調べてみるとこのエラーが出る状況は色々あるようで、その中の一つが以下の例なのでもし参考になればと思い投稿しました。

状況としては以下のように preconcurrencyなAVFoundationやSpeechを用いていたため、actorに隔離する必要があった。
また、値を特定のactorに隔離して監視したい要件があっため global actorを利用することになった。

import AVFoundation
import Speech

@globalActor
public struct SpeechActor {
  public actor ActorType {}
  public static let shared: ActorType = ActorType()
}

@SpeechActor
public final class SpeechRecognizer {

}

そして、このglobal actor内の以下の部分で毎回クラッシュした

func prepareEngine() throws -> (AVAudioEngine, SFSpeechAudioBufferRecognitionRequest) {
    let (audioEngine, request) = (AVAudioEngine(), SFSpeechAudioBufferRecognitionRequest())
    request.shouldReportPartialResults = true
    request.requiresOnDeviceRecognition = false
    let audioSession = AVAudioSession.sharedInstance()
    try audioSession.setCategory(.playAndRecord, mode: .measurement, options: .duckOthers)
    try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
    let inputNode = audioEngine.inputNode
    let recordingFormat = inputNode.outputFormat(forBus: 0)
    inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, _) in
      request.append(buffer)
    }
    audioEngine.prepare()
    try audioEngine.start()
    return (audioEngine, request)
  }

エラーはIncorrect actor executor assumptionと表示されていた
そもそもここにある、audioEngineやSFSpeechAudioBuffer...などはSendableに準拠できない参照型(reference type)のインスタンスであり、内部で他のactor等が使われていた場合に値が別のactorに隔離されているとその値を取得できないということになりかねない(あくまでも予想)

調べてもよくわからなかったが、global actorに隔離されていることがまずいのであれば nonisolatedで呼んでみれば良いでのはと試したところうまく行った。
つまり

  nonisolated static func prepareEngine() throws -> (AVAudioEngine, SFSpeechAudioBufferRecognitionRequest) {
    let (audioEngine, request) = (AVAudioEngine(), SFSpeechAudioBufferRecognitionRequest())
    request.shouldReportPartialResults = true
    request.requiresOnDeviceRecognition = false
    let audioSession = AVAudioSession.sharedInstance()
    try audioSession.setCategory(.playAndRecord, mode: .measurement, options: .duckOthers)
    try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
    let inputNode = audioEngine.inputNode
    let recordingFormat = inputNode.outputFormat(forBus: 0)
    inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, _) in
      request.append(buffer)
    }
    audioEngine.prepare()
    try audioEngine.start()
    return (audioEngine, request)
  }

こうすると上記のクラッシュに合わずに済んだ。

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?