A instância de Process
retornada por
Environment.process()
pode ser usada para interagir com o processo.
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.
Esperando por um Processo¶
Como 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.
Vamos assumir 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.
Poderiamos alterar o modelo adicionando ao carro o processo charge()
.
Antes, é preciso refatorar nossa classe carro para que os processos tenham
dois métodos:
run()
( o qual 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('Estacionando e carregando em %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))
...
... # Ao termino do carregamento então podemos
... # voltar a dirigir.
... print('Dirigindo em %d' % self.env.now)
... trip_duration = 2
... yield self.env.timeout(trip_duration)
...
... def charge(self, duration):
... yield self.env.timeout(duration)
Iniciando a simulação novamente: Nós criamos um ambiente/environment, um
( ou mais ) carros e finalmente chamamos o método run()
.
>>> import simpy
>>> env = simpy.Environment()
>>> car = Car(env)
>>> env.run(until=15)
Estacionando e carregando em 0
Dirigindo em 5
Estacionando e carregando em 7
Dirigindo em 12
Estacionando e carregando em 14
Interrompendo a execução de outro Processo¶
Digamos que você não quer aguardar até que o carro elétrico esteja completamente carregado e sim deseja parar o processo de carga para 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
tem uma referência para 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('Estacionando e carregando em %d' % self.env.now)
... charge_duration = 5
... # Caso seja interrompido enquanto carrega a bateria
... try:
... yield self.env.process(self.charge(charge_duration))
... except simpy.Interrupt:
... # Ao receber a solicitacao de interrupcao do processo
... # de carga, nos paramos de carregr e mudamos o estado
... # para "dirigindo"/"driving"
... print('Interrompido o processo. Espero que a bateria tenha carga suficiente ...')
... print('Dirigindo em %d' % self.env.now)
... trip_duration = 2
... yield self.env.timeout(trip_duration)
...
... def charge(self, duration):
... yield self.env.timeout(duration)
Se compararmos as mensagens de saída da simulação anterior com a atual,
veremos que o carro agora começa a ser dirigido em 3
ao invés de 5
:
>>> env = simpy.Environment()
>>> car = Car(env)
>>> env.process(driver(env, car))
<Process(driver) object at 0x...>
>>> env.run(until=15)
Estacionando e carregando em 0
Interrompido o processo. Espero que a bateria tenha carga suficiente ...
Dirigindo em 3
Estacionando e carregando em 5
Dirigindo em 10
Estacionando e carregando em 12
E agora?¶
Nós demonstramos apenas dois métodos simples para interação com os processos—esperando por um processo e interrompendo um processo. Dê uma olhada em Topical Guides ou documentação da API Process
para maiores detalhes.
Na próxima seção vamos enteder o básico da utilização de recursos compartilhados.