Sobes.tech
Middle

Трябва ли да използвате асинхронен изпълнител в този случай?

sobes.tech AI

Отговор от AI

Да, необходимо е.

Когато достъпвате actor отвън от изолиран контекст (в този случай от глобалния контекст), компилаторът гарантира безопасност на нишките, изисквайки асинхронен достъп.

// Демонстрационен протокол
protocol DataFetcher {
    func fetchData() async -> String
}

actor DataCache {
    var cache: [String: String] = [:]

    func updateCache(key: String, value: String) {
        cache[key] = value // Изпълнява се в изолиран контекст на актор
    }

    func cachedData(forKey key: String) -> String? {
        return cache[key] // Изпълнява се в изолиран контекст на актор
    }

    nonisolated func clearCacheIsolated() {
        // Тази функция е маркирана като nonisolated и няма достъп до състоянието на актор
        // За достъп е необходим асинхронен повик
    }
}


class DataLoader {
    let cache: DataCache // Връзка към актор

    init(cache: DataCache) {
        self.cache = cache
    }

    func loadData(key: String) async -> String {
        // Асинхронен достъп до актор
        if let cached = await cache.cachedData(forKey: key) {
            return cached
        }

        // ... логика за зареждане на данни ...
        let newData = "Data for \(key)"

        // Асинхронно обновяване на актор
        await cache.updateCache(key: key, value: newData)

        return newData
    }

    func attemptClearCacheAsync() async {
        // Асинхронен повик към метода на актор отвън
        await cache.clearCacheIsolated()
    }

    func attemptClearCacheDirect() {
        // Грешка при компилация:
        // Методът `clearCacheIsolated()` на актор-изолирана инстанция не може да бъде
        // извикан от не-изолирана среда
        // cache.clearCacheIsolated()
    }
}

В този пример:

  • Методите updateCache и cachedData се изпълняват в изолиран контекст на DataCache и са достъпни синхронно вътре в актор.
  • Обажданията към cache.cachedData(forKey: key) и cache.updateCache(key: key, value: newData) от метода loadData (който е извън контекста на actor) изискват ключовата дума await, което означава асинхронно изпълнение и използване на асинхронен изпълнител. Изпълнителят на actor отговаря за изпълнението на тези операции в ред, гарантирайки ексклузивен достъп до състоянието на actor.
  • Методът clearCacheIsolated е маркиран като nonisolated, но дори и към него е валиден асинхронен повик await cache.clearCacheIsolated() отвън на actor, въпреки че това не е задължително за гарантиране на безопасност на нишките в този случай (тъй като методът не променя състоянието на актор).
  • Пряк синхронен повик cache.clearCacheIsolated() от не-изолирана среда (като в attemptClearCacheDirect) води до грешка при компилация, потвърждавайки необходимостта от асинхронен достъп.

Следователно, за безопасно взаимодействие с actor отвън неговия контекст е необходимо да се използват асинхронни повиквания, които се изпълняват с помощта на асинхронен изпълнител, управляван от самия актор.