1
2
3
4 """
5 Asynchronous utilities for use with the
6 U{Twisted<http://twistedmatrix.com/>} library.
7 """
8
9 from twisted.internet import defer, reactor
10
12 """
13 Acts as the asynchronous version of C{time.sleep}.
14
15 @param seconds: The amount of time in seconds to sleep.
16 @type seconds: float
17
18 @return: The C{defer.Deferred} that will be fired on wake-up.
19 @rtype: defer.Deferred
20 """
21 d = defer.Deferred()
22 reactor.callLater( seconds, lambda: d.callback( None ) )
23 return d
24
26 """
27 Acts as the asynchronous version of a C{synchronized} decorator
28 (inspired by Java's keyword). Ensures that no event-handling path
29 (the asynchronous equivalent to threads) will enter the function
30 if another one is currently in it (which can happen if the current
31 "thread" is itself waiting on a deferred, thus giving the reactor
32 an opportunity to execute the competing "thread").
33
34 Provides additional protection against U{Twisted bug
35 411<http://twistedmatrix.com/trac/ticket/411>}. In this case, if
36 too many acquisition requests are chained onto the deferred which
37 is fired on release, then the stack will overflow. This is
38 circumvented by maintaining a queue of closures and deferreds
39 which is checked on each release, to keep the callback chain
40 "flat."
41
42 @param func: The function to decorate.
43 @type func: function
44
45 @return: The "thread-safe" version of the function.
46 @rtype: function
47 """
48 def wrapper( self, *args, **kwargs ):
49 try:
50 q = self._sync_queue
51 except AttributeError:
52 q = self._sync_queue = []
53 def release( result ):
54 invoke, d = q[0]
55
56
57
58 d.callback( result )
59
60 del q[0]
61 if len( q ) > 0:
62 invoke, d = q[0]
63
64
65 reactor.callLater( 0, invoke )
66 return result
67 def invoke():
68 return defer.maybeDeferred( func, self, *args, **kwargs ).addCallback( release )
69 d = defer.Deferred()
70 q.append( ( invoke, d ) )
71 if len( q ) == 1:
72 reactor.callLater( 0, invoke )
73 return d
74 wrapper.__name__ = func.__name__
75 wrapper.__dict__ = func.__dict__
76 wrapper.__doc__ = func.__doc__
77 return wrapper
78