async

Trabalhadores e tarefas assíncronas

Importação

_ <- fat.async

Tipos

A biblioteca async introduz o tipo Worker.

Worker

O Worker é um simples invólucro para uma operação assíncrona.

Construtor

Nome Assinatura Breve descrição
Worker (task: Method) Cria um Worker em modo espera

O construtor Worker aceita dois argumentos:

  • task: O método a ser executado de forma assíncrona (o método pode não aceitar argumentos diretamente, mas você pode adicionar esses usando duas setas na definição -> ->).
  • wait (opcional): O tempo limite em milissegundos. Se a tarefa não terminar dentro desse tempo, ela será cancelada.

Membros do protótipo

Nome Assinatura Breve descrição
start (): Worker Inicia a tarefa
cancel (): Void Cancela a tarefa
await (): Worker Aguarda pela conclusão da tarefa
isDone (): Boolean Verifica se a tarefa foi concluída
hasStarted Boolean Definido pelo método start
hasAwaited Boolean Definido pelo método await
isCanceled Boolean Definido pelo método cancel
result Any Definido pelo método await

Métodos avulsos

Nome Assinatura Breve descrição
atomic (op: Method): Any Executa a operação atomicamente
selfCancel (): Void Encerra a execução da thread
processors (): Number Retorna o número de processadores

Notas de uso

As instâncias de Worker são mapeadas para threads do sistema em uma base um-para-um e são executadas conforme o agendamento do sistema. Isso implica que sua execução pode nem sempre ser imediata. Para aguardar o resultado de um Worker, use o método await.

Diferentemente de outros contextos, no código assíncrono, a task: Method executa sem acesso ao escopo no qual é criada. Ela só pode acessar propriedades que foram 'curryficadas' -> -> para dentro do seu escopo de execução ou aquelas que estão diretamente acessíveis no escopo global.

O limite global de memória é compartilhado por todos os Workers, mas um contexto completamente novo, incluindo uma pilha separada, é alocado para cada um. No entanto, em caso de um erro irrecuperável ou fatal, como a exaustão de memória ou de pilha por um dos Workers, o interpretador será interrompido e todas as threads serão encerradas.

para manter o máximo desempenho, evite usar interpolação de texto dentro de tarefas assíncronas

Exemplos

async <- fat.async
math  <- fat.math
time  <- fat.time

# Define uma tarefa lenta
slowTask = (seconds: Number): Text -> -> {
  time.wait(seconds * 1000)
  'done'
}

# Inicia a tarefa como Worker
worker = Worker(slowTask(5)).start

# Obtém o resultado do worker
result1 = worker.await.result  # bloqueia até a tarefa ser concluída

# Inicia uma tarefa com timeout
task = Worker(slowTask(5), 3000).start  # a tarefa deve expirar

# Obtém o resultado da tarefa
result2 = task.await.result  # bloqueia até a tarefa ser concluída ou ocorrer timeout

o método await da gera um AsyncError se a tarefa exceder o tempo antes da conclusão

atomic

O encapsulador atomic é uma ferramenta crítica para garantir a segurança das threads e a integridade dos dados na programação concorrente. Quando múltiplos workers ou tarefas assíncronas acessam e modificam recursos compartilhados, condições de corrida podem ocorrer, levando a resultados imprevisíveis e errôneos. A operação atomic aborda essa questão garantindo que o método que ela envolve seja executado de forma atômica. Isso significa que a operação inteira é completada como uma única unidade indivisível, sem possibilidade de outras threads intervirem no meio do caminho para a mesma operação. Isso é particularmente importante para operações como incrementar um contador, atualizar estruturas de dados compartilhadas ou arquivos, ou realizar qualquer ação onde a ordem de execução importa:

async.atomic(-> file.append(logFile, line))

Embora as operações atomic sejam uma ferramenta poderosa para garantir a consistência, é importante estar atento ao potencial de contenção que elas introduzem. A contenção ocorre quando múltiplas "threads" ou tarefas tentam executar uma operação simultaneamente, levando a potenciais gargalos de desempenho à medida que cada tarefa espera sua vez. O uso excessivo ou desnecessário de operações atomic pode degradar significativamente o desempenho de sua aplicação, reduzindo a concorrência. Mantenha apenas a seção crítica de código que absolutamente requer atomicidade envolvida como uma operação atomic.

por baixo dos panos, operações atômicas são fundamentalmente protegidas por um único mutex global

Async na Web Build

Ao usar fry compilado com Emscripten (por exemplo, ao usar FatScript Playground), o suporte limitado da plataforma para multithreading afeta a implementação do Worker. Para maximizar a compatibilidade do código entre plataformas, as tarefas do Worker são executadas inline e bloqueiam a thread principal quando o método start é chamado. Esta abordagem compromete as vantagens da execução assíncrona, mas permite uma implementação consistente entre plataformas em muitos dos cenários.

Veja também

results matching ""

    No results matching ""