I'm confused about Simpy events and the ordering in which things happen. In the code below, the sender process generates an event every tick and gives it a unique sequence number. The receiver process is waiting on this event and prints the sequence number when received. The output of the code is:
Sender sent req at time 0 with num 0
Receiver Received req at time 0 with num 0
Sender sent req at time 1 with num 1
Receiver Received req at time 1 with num 1
Sender sent req at time 2 with num 2
Receiver Received req at time 2 with num 2
Sender sent req at time 3 with num 3
Receiver Received req at time 3 with num 3
Sender sent req at time 4 with num 4
Receiver Received req at time 4 with num 4
In other words, the receiver is woken up only once for every event that the sender sends. However, I'm not sure if this is entirely safe and will consistently work like this. For example, is the following sequence possible where the receiver could see the same event twice?
Please can you help me understand exactly how this ordering works.
Thanks.
import simpy
class Test:
def __init__(self, env):
self.env = env
self.req = env.event()
self.ack = env.event()
self.env.process(self.sender())
self.env.process(self.receiver())
def sender(self):
num = 0
while True:
self.req.succeed(num)
print('Sender sent req at time %d with num %s' % (self.env.now, num))
# Assert req for 1 cycle
yield self.env.timeout(1)
self.req = self.env.event()
num += 1
def receiver(self):
while True:
val = yield self.req
print('Receiver Received req at time %d with num %s' % (self.env.now, val))
yield self.env.timeout(1)
env = simpy.Environment()
test = Test(env)
env.run(until=25)
No, you cannot rely on the order events will happen at a tick. In general, if you want to do things in a asynchronous way you need a queue. In my example I use simpy Stores as message queues. Note that this just demos how to do some communicating and may need some changes to sim the protocol you are going for.
import simpy
class Test:
def __init__(self, env):
self.env = env
self.req = simpy.Store(env)
self.ack = simpy.Store(env)
self.env.process(self.sender())
self.env.process(self.receiver())
def sender(self):
num = 0
while True:
req = self.env.event()
self.req.put(req)
print('Sender sent req at time %d with num %s' % (self.env.now, num))
# take some time to send req
yield self.env.timeout(1)
req.succeed(num)
# wait for ack
ack = yield self.ack.get()
print('Sender got ack at time %d' % (self.env.now))
val = yield ack
print('Sender ack triggered at time %d with num %s' % (self.env.now, val))
num += 1
def receiver(self):
while True:
req = yield self.req.get()
print('Receiver Received req at time %d' % (self.env.now))
val = yield req
print('Receiver req triggered at time %d with num %s' % (self.env.now, val))
ack = self.env.event()
self.ack.put(ack)
# take some time to send ack
yield self.env.timeout(1)
ack.succeed(val)
print('Receiver finished sending ack at time %d with num %s' % (self.env.now, val))
env = simpy.Environment()
test = Test(env)
env.run(until=25)