3

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

Cactusman
  • 335
  • 3
  • 12
  • Just read up on what "with" actually does. It just calls routines of the object (i think__enter__ and__close__, but can't remember). And then do something like that. Why do you not want to use "with... As..." though? – will May 18 '14 at 22:37

3 Answers3

6

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)
Stefan Scherfke
  • 3,012
  • 1
  • 19
  • 28
  • Exactly what I was asking. My inexperience with Python-generators made learning SimPy harder than it should have been. Thanks for developing SimPy! – Cactusman May 20 '14 at 21:50
  • What about if I have multiple resources that I would like to "clear" after each time unit? Maybe I'm not formulating this the right way, but I would like my process to consume 2 units of the resource, so I did `req = resource.request()` twice. However, when I do `resource.release(req)`, regardless of how many times I call this 1 resource still remains in use according to `resource.count` – windyvation Aug 06 '21 at 16:57
3

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.

dano
  • 91,354
  • 19
  • 222
  • 219
  • You get back the cleanup code using `try:...finally:` but then it might as well just use `with`... – will May 18 '14 at 22:58
  • Thanks, I coded up this example (based on the SimPy website doc.) based on reading your post: https://gist.github.com/ndmacdon/1b43b8f29e66fee7a5e1#file-simpyrequestrelease – Cactusman May 18 '14 at 23:39
0

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.

will
  • 10,260
  • 6
  • 46
  • 69