Interação entre Processos¶
A instância de Process retornada por Environment.process() pode ser usada para interagir com o processo.:meth:Environment.process() can be utilized for process interactions. Dois exemplos mais comuns de uso são para aguardar o término de algum outro processo e interromper a execução de outro processo enquanto se espera por um evento.
Aguardando por um Processo¶
Conforme mencionado, um Process Simpy pode ser usado como um evento ( tecnicamente falando, um processo é um evento). Se você marcá-lo com yield, ele continua uma vez que o processo tenha concluído. Imagine a simulação de uma lava a jato onde os carros entram para a limpeza e aguardam que o processo de lavagem seja concluído. Ou uma simulação de um aeroporto onde os passageiros tem de esperar até que os procedimentos de segurança sejam concluídos.
Considerando que o carro do nosso exemplo anterior, vire do nada um carro elétrico. Carros elétricos geralmente levam muito tempo carregando suas baterias após uma viagem. Eles teriam de esperar até que suas baterias estivessem carregadas para que continuassem sua viagem.
Poderíamos alterar o modelo adicionando ao carro o processo charge(). Antes, é preciso refatorar nossa classe carro para que os processos tenham dois métodos: run() ( que antes era a função car() ) e charge().
O processo run é iniciado automaticamente quando Car é instanciado. E um processo charge é chamado toda vez que o carro começa a estacionar. Ao se solicitar uma instância de Process retornado pelo método Environment.process(), o processo run fica aguardando o término do evento:
>>> class Car(object):
... def __init__(self, env):
... self.env = env
... # Start the run process everytime an instance is created.
... self.action = env.process(self.run())
...
... def run(self):
... while True:
... print('Start parking and charging at %d' % self.env.now)
... charge_duration = 5
... # We yield the process that process() returns
... # to wait for it to finish
... yield self.env.process(self.charge(charge_duration))
...
... # The charge process has finished and
... # we can start driving again.
... print('Start driving at %d' % self.env.now)
... trip_duration = 2
... yield self.env.timeout(trip_duration)
...
... def charge(self, duration):
... yield self.env.timeout(duration)
Reiniciando a simulação: Nós criamos um ambiente/environment que contém um ( ou mais ) carros e finalmente chamamos o método run().
>>> import simpy
>>> env = simpy.Environment()
>>> car = Car(env)
>>> env.run(until=15)
Start parking and charging at 0
Start driving at 5
Start parking and charging at 7
Start driving at 12
Start parking and charging at 14
Interrompendo a execução de um objeto Process qualquer¶
Digamos que você não quer aguardar até que o carro elétrico esteja completamente carregado, para isso terá de parar o processo de carga para então, começar a dirigir.
SimPy permite que você interrompa a execução de um processo chamando o método interrupt()
>>> def driver(env, car):
... yield env.timeout(3)
... car.action.interrupt()
O processo driver``(dirigir) tem uma referência para o processo ``action do carro. Depois de esperar por 3 passos da simulação, ele interrompe aquele processo.
As interrupções são aplicadas nos processos como exceções Interrupt que podem (ou devem) ser tratadas pelo processo que foi interrompido. O processo por sua vez pode então decidir o que fazer em seguida (por exemplo: continuar a esperar o evento que o originou ou iniciar um novo evento):
>>> class Car(object):
... def __init__(self, env):
... self.env = env
... self.action = env.process(self.run())
...
... def run(self):
... while True:
... print('Start parking and charging at %d' % self.env.now)
... charge_duration = 5
... # We may get interrupted while charging the battery
... try:
... yield self.env.process(self.charge(charge_duration))
... except simpy.Interrupt:
... # When we received an interrupt, we stop charging and
... # switch to the "driving" state
... print('Was interrupted. Hope, the battery is full enough ...')
...
... print('Start driving at %d' % self.env.now)
... trip_duration = 2
... yield self.env.timeout(trip_duration)
...
... def charge(self, duration):
... yield self.env.timeout(duration)
Ao comparar as mensagens de saída da simulação anterior com a atual, veremos que o carro agora começa a ser dirigido no tempo 3 ao invés do tempo 5:
>>> env = simpy.Environment()
>>> car = Car(env)
>>> env.process(driver(env, car))
<Process(driver) object at 0x...>
>>> env.run(until=15)
Start parking and charging at 0
Was interrupted. Hope, the battery is full enough ...
Start driving at 3
Start parking and charging at 5
Start driving at 10
Start parking and charging at 12
A seguir…¶
Foram demonstrados apenas dois métodos simples para interação com os processos—esperando por um processo e interrompendo um processo. Dê uma lida em Topical Guides ou na documentação da API Process para maiores detalhes.
Na próxima seção vamos enteder o básico sobre a utilização de recursos compartilhados.