Reputation: 345
I'm trying to add SimPy simulation to a project I'm working on and I have some confusion about version 3's release/request.
I was able to implement resources using a 'with'-block without trouble but in my situation I want to request/release a resource without using a 'with'-block.
However, I cannot find an example of this using SimPy 3. I read the documentation/source regarding resources but still can't get it quite right. Could someone explain how to properly:
...
Request a Resource with the method: 'request()'
...
Release that Resource with the method: 'release()'
...
Thanks, and sorry for the bother.
PS: I'm intending to use Resources.resource
Upvotes: 3
Views: 2531
Reputation: 3232
If you want to use a resource without a with
block (and you know you won’t get interrupted), its just:
req = resource.request()
yield req
# do stuff
resource.release(req)
Upvotes: 6
Reputation: 94951
Using with
on an object calls __enter__
when you enter the with
block, and __exit__
when you leave. So when you do
res = resource.Resource()
with res.request() as req:
# stuff
You're really calling __enter__
on a Request object, doing #stuff
then calling __exit__
:
class Request(base.Put):
def __exit__(self, exc_type, value, traceback):
super(Request, self).__exit__(exc_type, value, traceback)
self.resource.release(self)
class Put(Event): # base.Put
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
# If the request has been interrupted, remove it from the queue:
if not self.triggered:
self.resource.put_queue.remove(self)
So, the with
block is equivalent to this:
res = resource.Resource(...)
req = res.request()
#stuff
if not req.triggered:
res.put_queue.remove(req)
res.release(req)
However, the with
block is also making sure that the cleanup code is called no matter what exceptions are thrown during #stuff
. You'll lose that with the above code.
Upvotes: 3
Reputation: 10650
It's all outlined in PEP343;
with EXPR as VAR:
BLOCK
becomes:
mgr = (EXPR)
exit = type(mgr).__exit__ # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
try:
VAR = value # Only if "as VAR" is present
BLOCK
except:
# The exceptional case is handled here
exc = False
if not exit(mgr, *sys.exc_info()):
raise
# The exception is swallowed if exit() returns true
finally:
# The normal and non-local-goto cases are handled here
if exc:
exit(mgr, None, None, None)
This is exactly how python uses with... as...
blocks, but I'm presuming there's some reason you don't want to use these. If that's the case, then you just need the __enter__
and __exit__
functions. The way i think of it, is __enter__
sets everything up, and __exit__
does all the cleanup.
Upvotes: 0