[Twisted-Python] DeferredSemaphore - action on acquire and release
I'm using a DeferredSemaphore with a token count of 1 to control access to a serial port. I also have a GTK object for which I'd like the "in-use" property to change (and notify listeners) when the resource is in use. So far, I have something like this: ---- class SerialResource(gobject): # Property defs, etc def _acquire(self): # The "in-use" property is actually stored in self.taken self.taken = True self.notify('in-use') def _release(self, res): self.taken = False self.notify('in-use') return res def run(self, func, *args, **kargs): def wrapper(): self._acquire() res = func(*args, **kargs) return res d = self.sem.run(wrapper) d.addBoth(self._release) return d ---- I feel like there might be a simpler way to do this, but I just can't see it. Or is this as simple as I can make it? — Jason
I think what you have duplicating functionality---you're not taking advantage of the DeferredSemaphore. Try something like this: sem = DeferredSemaphore(1) def doSerialStuffAndRelease(sem): # ...perform serial port communication... sem.release() d = sem.acquire() d.addCallback(doSerialStuffAndRelease) You'll want "sem" to be a global---use wherever you deal with a particular port. Create additional instances of DeferredSemaphore for additional serial ports. Note that when the deferred is fired, the semaphore is passed as the argument. This is the reason for "sem" being the argument name in the function. http://twistedmatrix.com/trac/browser/tags/releases/twisted-10.2.0/twisted/i... Note that you'll also want an error handler which releases the semaphore :) Jason On Mon, Feb 7, 2011 at 8:23 PM, Jason Heeris <jason.heeris@gmail.com> wrote:
I'm using a DeferredSemaphore with a token count of 1 to control access to a serial port. I also have a GTK object for which I'd like the "in-use" property to change (and notify listeners) when the resource is in use. So far, I have something like this:
---- class SerialResource(gobject):
# Property defs, etc
def _acquire(self): # The "in-use" property is actually stored in self.taken self.taken = True self.notify('in-use')
def _release(self, res): self.taken = False self.notify('in-use') return res
def run(self, func, *args, **kargs): def wrapper(): self._acquire() res = func(*args, **kargs) return res
d = self.sem.run(wrapper) d.addBoth(self._release) return d ----
I feel like there might be a simpler way to do this, but I just can't see it. Or is this as simple as I can make it?
— Jason
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
-- Jason Rennie Research Scientist, ITA Software 617-714-2645 http://www.itasoftware.com/
On 8 February 2011 10:45, Jason Rennie <jrennie@gmail.com> wrote:
I think what you have duplicating functionality---you're not taking advantage of the DeferredSemaphore.
I thought using the "run" method *was* the preferred way to use a DS, but whatever works.
You'll want "sem" to be a global---use wherever you deal with a particular port.
There's one serial settings object for the life of the program (which, since it is initialised in my main entry point, is essentially global), and I'm happy to let it "own" the semaphore. Making the DS itself global won't really get me anything better than that. and Stephen Thorne... On 2011-02-07, Jason Rennie wrote:
d = sem.acquire() d.addCallback(doSerialStuffAndRelease)
Shouldn't this be spelled:
d = sem.run(doSerialStuff)
Which does acquasition and release of the sempahore properly?
Won't you then be trying to acquire or release it twice? — Jason
On 2011-02-08, Jason Heeris wrote:
On 8 February 2011 10:45, Jason Rennie <jrennie@gmail.com> wrote:
I think what you have duplicating functionality---you're not taking advantage of the DeferredSemaphore.
I thought using the "run" method *was* the preferred way to use a DS, but whatever works.
Shouldn't this be spelled:
d = sem.run(doSerialStuff)
Which does acquasition and release of the sempahore properly?
Won't you then be trying to acquire or release it twice?
Um, that's what I mean, you shouldn't be using .acquire() or .release(), just .run(). doSerialStuff doesn't need a reference to the semaphore object. -- Regards, Stephen Thorne Development Engineer Netbox Blue
On 8 February 2011 11:46, Stephen Thorne <stephen@thorne.id.au> wrote:
Um, that's what I mean, you shouldn't be using .acquire() or .release(), just .run(). doSerialStuff doesn't need a reference to the semaphore object.
So... how can I update the property and emit the signal upon acquisition and release? Or are you saying I should stick with what I had? — Jason
On 2011-02-08, Jason Heeris wrote:
On 8 February 2011 11:46, Stephen Thorne <stephen@thorne.id.au> wrote:
Um, that's what I mean, you shouldn't be using .acquire() or .release(), just .run(). doSerialStuff doesn't need a reference to the semaphore object.
So... how can I update the property and emit the signal upon acquisition and release? Or are you saying I should stick with what I had?
I totally misread your example, and I appologise. I've read it now and it looks fine to me. The only commend I'd make is that you probably want DeferredLock not DeferredSempahore if this is serialised access. -- Regards, Stephen Thorne Development Engineer Netbox Blue
On 8 February 2011 12:22, Stephen Thorne <stephen@thorne.id.au> wrote:
I totally misread your example, and I appologise. I've read it now and it looks fine to me. The only commend I'd make is that you probably want DeferredLock not DeferredSempahore if this is serialised access.
No need to apologise, happens to anyone :) And thanks for the pointer to DeferredLock, somehow I totally missed that. Cheers, Jason
Sorry, I don't think I understand the example either---looks to me like you're reimplementing a semaphore. Stephen's right about run(). Cheers, Jason On Mon, Feb 7, 2011 at 11:37 PM, Jason Heeris <jason.heeris@gmail.com>wrote:
On 8 February 2011 12:22, Stephen Thorne <stephen@thorne.id.au> wrote:
I totally misread your example, and I appologise. I've read it now and it looks fine to me. The only commend I'd make is that you probably want DeferredLock not DeferredSempahore if this is serialised access.
No need to apologise, happens to anyone :) And thanks for the pointer to DeferredLock, somehow I totally missed that.
Cheers, Jason
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
-- Jason Rennie Research Scientist, ITA Software 617-714-2645 http://www.itasoftware.com/
On 01:14 pm, jrennie@gmail.com wrote:
Sorry, I don't think I understand the example either---looks to me like you're reimplementing a semaphore. Stephen's right about run().
It sounds like (the other) Jason would be happy with run, except he also wants to do something extra each time the lock/semaphore is taken and released. DeferredSemaphore (and the other similar classes) don't really offer this functionality. You just have to work that logic into the function you run. It's possible something like this would be nicer than reimplementing the acquire/release logic: def run(sem, f): def before(): doAcquire() return f() d = sem.run(before) def after(passthrough): doRelease() return passthrough d.addBoth(after) return d Jean-Paul
participants (4)
-
exarkun@twistedmatrix.com
-
Jason Heeris
-
Jason Rennie
-
Stephen Thorne