Add python-eventlet 0.16.1
[packages/trusty/python-eventlet.git] / eventlet / eventlet / coros.py
1 from __future__ import print_function
2
3 from eventlet import event as _event
4
5
6 class metaphore(object):
7     """This is sort of an inverse semaphore: a counter that starts at 0 and
8     waits only if nonzero. It's used to implement a "wait for all" scenario.
9
10     >>> from eventlet import coros, spawn_n
11     >>> count = coros.metaphore()
12     >>> count.wait()
13     >>> def decrementer(count, id):
14     ...     print("{0} decrementing".format(id))
15     ...     count.dec()
16     ...
17     >>> _ = spawn_n(decrementer, count, 'A')
18     >>> _ = spawn_n(decrementer, count, 'B')
19     >>> count.inc(2)
20     >>> count.wait()
21     A decrementing
22     B decrementing
23     """
24
25     def __init__(self):
26         self.counter = 0
27         self.event = _event.Event()
28         # send() right away, else we'd wait on the default 0 count!
29         self.event.send()
30
31     def inc(self, by=1):
32         """Increment our counter. If this transitions the counter from zero to
33         nonzero, make any subsequent :meth:`wait` call wait.
34         """
35         assert by > 0
36         self.counter += by
37         if self.counter == by:
38             # If we just incremented self.counter by 'by', and the new count
39             # equals 'by', then the old value of self.counter was 0.
40             # Transitioning from 0 to a nonzero value means wait() must
41             # actually wait.
42             self.event.reset()
43
44     def dec(self, by=1):
45         """Decrement our counter. If this transitions the counter from nonzero
46         to zero, a current or subsequent wait() call need no longer wait.
47         """
48         assert by > 0
49         self.counter -= by
50         if self.counter <= 0:
51             # Don't leave self.counter < 0, that will screw things up in
52             # future calls.
53             self.counter = 0
54             # Transitioning from nonzero to 0 means wait() need no longer wait.
55             self.event.send()
56
57     def wait(self):
58         """Suspend the caller only if our count is nonzero. In that case,
59         resume the caller once the count decrements to zero again.
60         """
61         self.event.wait()