Aguardando múltiplos eventos
Uma funcionalidade importante do SimPy é permitir que uma entidade aguarde até que dois ou mais eventos ocorram para então prosseguir com o processo. O SimPy possui duas opções muito interessantes para isso:
simpy.nyOf(env, eventos):
aguarda até que um dos eventos tenham ocorrido -AnyOf
é equivalente ao símbolo de "|" (ouor
);simpy.AllOf(env, eventos):
aguarda até que todos os eventos tenham ocorrido -AllOf
é equivalente ao símbolo de "&" (ouand
).s
Para compreender o funcionamento dos comandos anteriores, partiremos de um exemplo baseado numa obscura fábula infantil: a Lebre e a Tartaruga.
Neste exemplo, sortearemos um tempo de corrida para cada bicho e identificaremos quem foi o vencedor. Para tanto, além do sorteio, criaremos dois eventos que representam a corrida de cada bicho:
Na função corrida,
criamos os eventos lebreEvent
e tartarugaEvent
, que simulam, respectivamente, as corridas da lebre e da tartaruga. Mas, lembre-se: apesar de criados, os eventos ainda não foram necessariamente executados. Como não existe um yield
aplicado aos eventos, eles foram criados na memória do Python, mas só serão considerados processados após o tempo de simulação avançar o suficiente para que os tempos de timeout
tenham passado.
De outra forma, os eventos lebreEvent
e tartarugaEvent
foram disparados, mas não processados, pois a função corrida
ainda não tem um comando que aguarda o término do processamento desses eventos.
Aguardando até que, ao menos, um evento termine com AnyOf
AnyOf
Para garantir que a função corrida
aguarde até que, ao menos, um dos corredores termine a prova, uma opção é acrescentar um yield AnyOf()
(que pode ser substituído por "|") após a criação dos eventos:
O yield
garante que a função aguardará até que um dos dois eventos - lebreEvent
ou tartarugaEvent
- termine e a variável resultado
armazenará qual desses eventos terminou primeiro (ou mesmo os dois, em caso de empate). Assim, para sabermos quem venceu, basta explorarmos o valor contido na variável resultado
.
O código a seguir completa o modelo, testando qual dos dois eventos está na variável resultado
:
Quando o modelo anterior é executado, o bicho pega:
Observação: a linha:
Poderia ter sido substituída, pela linha:
Aguardando todos os eventos com AllOf
AllOf
Para não deixar ninguém triste, poderíamos forçar um empante na corrida, aguardando que a função corrida
aguarde até que os dois eventos sejam concluídos para decretar o vencedor. Para isso, basta substituir a linha:
por:
Quando simulado, o novo modelo forncece como saída:
O que ocorreu? Neste caso, o comando AllOf
(ou "&") aguardou até que os dois eventos terminassem para liberar o processamento da linha seguinte de código e nosso desvio de condição if
identificou que a variável resultado
possuia os dois eventos armazenados.
Comprendendo melhor as saídas dos comandos AllOf
e AnyOf
AllOf
e AnyOf
Agora que já sabemos o que fazem os comandos AllOf
e AnyOf
, vamos explorar nessa seção um pouco mais sobre o que exatamente esses comandos retornam.
Inicialmente, imprima os valores dos eventos e da variável resultado
, para descobrir seus conteúdos:
Quando executado, o programa fornece:
Pela saída anterior, descobrimos, inicialmente, que os eventos são objetos do tipo Timeout
e que armazenam tanto o tempo de espera, quanto o valor (ou value
) fornecido na chamada da função env.timeout.
Um pouco mais abaixo, a saída revela que a variável resultado
é um objeto da classe ConditionValue
que, aparentemente, contém um dicionário de eventos em seu interior. Para acessar esse dicionário, o SimPy fornece o método .todict():
Que retorna:
Que nada mais é do que um dicionário padrão do Python, onde as keys
são os eventos e os items
são os valores dos eventos.
Conceitos desta seção
Conteúdo | Descrição |
| aguarda até que um dos eventos tenham ocorrido - |
| aguarda até que todos os eventos tenham ocorrido - |
Desafios
Desafio 23: Considere que existe uma probabilidade de que a Lebre, por alguma razão mal explicada (eu realizaria um teste antidoping nos competidores), resolva que é uma boa ideia tirar uma soneca de 5 minutos em algum instante entre 2 e 10 minutos do início da corrida. Modele esta nova situação (dica: crie um função
soneca
que gera um evento que pode ocasionar a parada da Lebre ainda durante a corrida).Desafio 24: É interessante notar, que mesmo quando um dos competidores perde a corrida, de fato, o respectivo evento não é cancelado. Altere o modelo anterior para marcar o horário de chegada dos dois competidores, garantindo que os eventos
lebreEvent
etartarugaEvent
sejam executados até o fim.
Last updated