Sobes.tech
Middle

É necessário usar um executor assíncrono neste caso?

sobes.tech IA

Resposta da IA

Sim, é necessário.

Ao aceder a actor de fora do seu contexto isolado (neste caso, do contexto global), o compilador garante a segurança de threads, exigindo que o acesso seja feito de forma assíncrona.

// Protocolo para demonstração
protocol DataFetcher {
    func fetchData() async -> String
}

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

    func updateCache(key: String, value: String) {
        cache[key] = value // Executado dentro do contexto isolado do ator
    }

    func cachedData(forKey key: String) -> String? {
        return cache[key] // Executado dentro do contexto isolado do ator
    }

    nonisolated func clearCacheIsolated() {
        // Esta função está marcada como nonisolated e não tem acesso ao estado do ator
        // Para aceder, é necessária uma chamada assíncrona
    }
}


class DataLoader {
    let cache: DataCache // Referência ao ator

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

    func loadData(key: String) async -> String {
        // Acesso assíncrono ao ator de fora
        if let cached = await cache.cachedData(forKey: key) {
            return cached
        }

        // ... lógica de carregamento de dados ...
        let newData = "Data for \(key)"

        // Atualização assíncrona do ator
        await cache.updateCache(key: key, value: newData)

        return newData
    }

    func attemptClearCacheAsync() async {
        // Chamada assíncrona ao método do ator de fora
        await cache.clearCacheIsolated()
    }

    func attemptClearCacheDirect() {
        // Erro de compilação:
        // Método de instância 'clearCacheIsolated()' isolado por ator não pode ser
        // chamado de um contexto não isolado
        // cache.clearCacheIsolated()
    }
}

Neste exemplo:

  • Os métodos updateCache e cachedData são executados dentro do contexto isolado de DataCache e acessíveis de forma síncrona dentro do ator.
  • Aceder a cache.cachedData(forKey: key) e cache.updateCache(key: key, value: newData) a partir do método loadData (que está fora do contexto do actor) requer a palavra-chave await, o que indica execução assíncrona e uso de um executor assíncrono. O executor do actor é responsável por executar estas operações em ordem, garantindo acesso exclusivo ao estado do actor.
  • O método clearCacheIsolated está marcado como nonisolated, mas até a sua chamada assíncrona await cache.clearCacheIsolated() é válida de fora do actor, embora não seja obrigatória para garantir a segurança de threads neste caso (uma vez que o método não altera o estado do actor).
  • A chamada síncrona direta cache.clearCacheIsolated() de um contexto não isolado (como em attemptClearCacheDirect) resulta num erro de compilação, confirmando a necessidade de acesso assíncrono.

Assim, para interagir de forma segura com um actor de fora do seu contexto, é necessário usar chamadas assíncronas que são executadas com a ajuda de um executor assíncrono gerido pelo próprio actor.