Uma expressão em Verse pode ser imediata ou assíncrona. Isso descreve o tempo que uma expressão pode levar para avaliar em relação a atualizações de simulação.
Pense em uma atualização de simulação como quando um novo quadro é exibido.
Há casos em que várias atualizações de simulação podem ocorrer antes de um novo quadro, como se um jogo online ficar fora de sincronia com o servidor.
| imediata | assíncrona |
|---|---|
Uma expressão imediata é avaliada sem atraso, o que significa que a avaliação será concluída dentro da atualização da simulação atual. | Uma expressão assíncrona pode levar tempo para ser avaliada, mas não necessariamente. Uma expressão assíncrona pode ou não ser concluída na atualização da simulação atual ou em uma posterior. |
Contextos assíncronos
Expressões assíncronas podem ser usadas em qualquer código do Verse que tenha um contexto assíncrono.
O contexto assíncrono é o corpo da função que tem o especificador de efeitos "suspends". O efeito suspends indica que funções assíncronas podem suspender e transferir cooperativamente o controle para outras expressões simultâneas em vários pontos durante várias atualizações de simulação antes de serem concluídas.
A função OnBegin() em um dispositivo Verse é uma função assíncrona comum usada como ponto de partida para o código assíncrono.
Chamar uma função assíncrona tem a mesma sintaxe que chamar uma função imediata:
OnBegin<override>()<suspends> : void =
HideAllPlatforms()
HideAllPlatforms()<suspends> : void =
for (Platform : Platforms):
Platform.Hide()
Sleep(Delay)Como qualquer outra expressão, uma expressão assíncrona pode ter um resultado. O resultado de uma expressão assíncrona apenas está disponível após a conclusão da expressão.
# Npc is undefined until it is bound after MoveToNearestNPC() completes which may be several frames into the future
Npc := Player.MoveToNearestNPC()
#Only called after MoveToNearestNPC() completes
Print("Moved to {Npc}")Blocos de código dentro de um contexto assíncrono (no corpo de uma função assíncrona) podem ter qualquer combinação de expressões assíncronas e imediatas.
Se qualquer expressão em um bloco de código for assíncrona, o bloco de código inteiro será considerado assíncrono.
Se todas as expressões em um bloco de código forem imediatas, o bloco de código inteiro será considerado imediato.
Todas as expressões no exemplo abaixo são expressões assíncronas, então o bloco de código inteiro é assíncrono:
Sleep(2.0) # waits 2 seconds
Boss.TauntEmote() # waits until TauntEmote() completes
Player.MoveToNearestNPC() # waits until MoveToNearestNPC() completesTodas as expressões no exemplo abaixo são expressões imediatas, então o bloco de código inteiro é imediato:
Print("Reset after explosion")
Platform.Show()
set SecondsUntilExplosion = 12.0As expressões no exemplo abaixo são uma mistura de expressões assíncronas e imediatas, então o bloco de código inteiro é assíncrono:
Print("Started")
var Seconds := 1.0
Sleep(Seconds)
Print("Waited {Second} seconds")
set Second += 1.0
Sleep(Seconds)
Print("Waited {Second} seconds")
set Second += 1.0
Expressões imediatas permanecem juntas por conta própria. Todas as expressões (não assíncronas) imediatas adjacentes são consideradas atômicas. Seu código será executado sem interrupção na mesma atualização e sem preempção ou troca de contexto. É como se esse código tivesse uma primitiva de exclusão mútua automática encapsulada ao sue redor.
Portanto, no exemplo de código acima, essas expressões imediatas são tratadas atomicamente:
# These two expressions are always kept together
Print("Started")
var Seconds := 1.0
Sleep(Seconds)
# These two expressions are always kept together
Print("Waited {Second} seconds")
set Second += 1.0
Como em qualquer outro bloco de código, a última expressão em um bloco de código assíncrono é usada como resultado.
Expressões de simultaneidade
Verse usa expressões de simultaneidade para determinar se expressões são executadas simultaneamente (ao mesmo tempo) ou em sequência, uma após a outro. Uma expressão assíncrona é executada ou invocada ao longo do tempo e, portanto, essas expressões de simultaneidade podem ser especialmente úteis quando você está usando expressões assíncronas.
Simultaneidade estruturada
Uma expressão assíncrona bloqueará a execução de outras expressões se demorar muito para ser executada. Por exemplo, usar Sleep(90.0) fará com que o programa espere 90 segundos, bloqueando a próxima expressão até que Sleep(90.0) seja totalmente executada.
Expressões de simultaneidade estruturada são usadas para especificar o fluxo de tempo lógico assíncrono e para modificar a natureza de bloqueio de expressões assíncronas com uma duração restrita logicamente a um escopo de contexto assíncrono específico (como um corpo de função assíncrona).
Isso é semelhante ao controle de fluxo estruturado, como block, if, for e loop que restringem seu respectivo escopo.
Expressões assíncronas em Verse não usam as primitivas yield e await usadas por implementações assíncronas em outras linguagens. Os mesmos mecanismos são alcançados quando se usam expressões de concorrência do Verse e mecanismos internos.
Para saber mais sobre simultaneidade estruturada, consulte Sync, Race, rush e ramificação.
Simultaneidade não estruturada
Existe apenas uma expressão de simultaneidade não estruturada: spawn. Essa expressão tem uma vida útil que não é logicamente restrita a um escopo de contexto assíncrono específico, mas que pode se estender potencialmente além do escopo em que foi executada.
A simultaneidade não estruturada é como uma saída de emergência: você não deve usá-la regularmente, embora às vezes seja sua melhor e única opção.
Expressões de simultaneidade estruturadas (sync, race, rush e branch) devem ser usadas antes de expressões de simultaneidade não estruturadas (spawn) sempre que possível.
Para saber mais sobre a simultaneidade não estruturada, consulte Spawn.
Tarefas para rastreamento de expressões assíncronas atualmente em execução
Uma expressão assíncrona tem uma tarefa associada a ela.
Uma tarefa é um objeto que representa uma função assíncrona que começou a ser executada, mas que foi suspensa para permitir que outra tarefa seja concluída.
A tarefa pode ser usada para verificar o status de uma expressão assíncrona e para cancelar esta última, se desejado.
Para saber mais sobre tarefas, consulte Tarefa.