Closed rayman4ever closed 5 years ago
Snippet of the output:
[600.00] TX: Sending
[600.00] RX: Queue len: 1
[610.00] RX: Timeout...
[630.00] RX: Queue len: 0
[640.00] RX: Timeout...
[650.00] TX: Sending
[660.00] RX: Queue len: 0
[670.00] RX: Timeout...
[690.00] RX: Queue len: 0
[700.00] TX: Sending
[700.00] RX: Timeout...
[720.00] RX: Queue len: 0
[730.00] RX: Timeout...
[750.00] TX: Sending
[750.00] RX: Queue len: 1
[760.00] RX: Timeout...
[780.00] RX: Queue len: 0
[790.00] RX: Timeout...
Hi,
I'm not sure this is great from a user's perspective, but the following happens. Although your code "lost" interest in event_b
after event_a
fired, the simpy engine still delivers event_b
. During your next loop, a new event_b
request is sent to the simpy engine, your code having effectively lost the ability to retrieve the one that fired in the previous loop. I slightly modified your code to reuse event_b
s across the loop if they are not consumed by your code:
from simpy import *
def dbg_log(env, msg):
tmp = '[%0.2f] %s' % (env.now, msg)
print(tmp)
def packet_receiver(env, q):
event_b = None
while True:
dbg_log(env, 'RX: Queue len: ' + str(len(q.items)))
event_a = env.timeout(10)
if event_b is None:
event_b = q.get()
condition = yield event_a | event_b
if event_a in condition:
dbg_log(env, 'RX: Timeout...')
else:
dbg_log(env, 'RX: received a packet...')
event_b = None
yield env.timeout(20)
def packet_transmitter(env, q):
yield env.timeout(500)
while True:
dbg_log(env, 'TX: Sending')
q.put(10)
dbg_log(env, 'TX: Sent')
yield env.timeout(50)
env = Environment()
packet_store = Store(env)
env.process(packet_receiver(env, packet_store))
env.process(packet_transmitter(env, packet_store))
dbg_log(env, "*** SIM START ***")
env.run(until=1000)
dbg_log(env, "*** SIM END ***")
I understand that this behaviour is counter-intuitive, but I'm wondering how a more intuitive solution should look like. Should AnyOf conditional cancel interest in unfired events? Should there be a way to del event_b
?
Interesting point! I think the event should be canceled too.
I think the main problem here is that when the timeout starts and the Store gets an element in the queue, it does not process the store event. It instead waits for the timeout to elapse.
The workaround I am using is:
t1 = env.now
while env.now < t1 + 1000:
if len(queue.items) > 0:
item = yield queue.get()
break
yield env.timeout(0.001) # small step
it works but it affects the simulation performance drastically.
I suggest you take my workaround. My workaround does not "lose" any events and, although looks ugly to read, it uses the simulation engine properly to wait for a timeout or packet arrival. Performance is therefore really good.
I am trying to implement a code where if the packet receiver does not receive a packet within a period of time it must report it to the console.
I realized the simpy engine does not process this correctly, digging deep I realized that the engine removes the callbacks from the event but I cannot understand why.
Code below:
Please help.