sources for dummy_greenlet.py [rev. 38799]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import thread, sys
__all__ = ['greenlet', 'main', 'getcurrent']
class greenlet(object):
    __slots__ = ('run', '_controller')
    def __init__(self, run=None, parent=None):
        if run is not None:
            self.run = run
        if parent is not None:
            self.parent = parent
    def switch(self, *args):
        global _passaround_
        _passaround_ = None, args, None
        self._controller.switch(self)
        exc, val, tb = _passaround_
        del _passaround_
        if exc is None:
            if isinstance(val, tuple) and len(val) == 1:
                return val[0]
            else:
                return val
        else:
            raise exc, val, tb
    def __nonzero__(self):
        return self._controller.isactive()
    def __new__(cls, *args, **kwds):
        self = object.__new__(cls)
        self._controller = _Controller()
        return self
    def __del__(self):
        #print 'DEL:', self
        if self._controller.parent is None:
            return   # don't kill the main greenlet
        while self._controller.isactive():
            self._controller.kill(self)
    def getparent(self):
        return self._controller.parent
    def setparent(self, nparent):
        if not isinstance(nparent, greenlet):
            raise TypeError, "parent must be a greenlet"
        p = nparent
        while p is not None:
            if p is self:
                raise ValueError, "cyclic parent chain"
            p = p._controller.parent
        self._controller.parent = nparent
    parent = property(getparent, setparent)
    del getparent
    del setparent
class _Controller:
    # Controllers are separated from greenlets to allow greenlets to be
    # deallocated while running, when their last reference goes away.
    # Care is taken to keep only references to controllers in thread's
    # frames' local variables.
    # _Controller.parent: the parent greenlet.
    # _Controller.lock: the lock used for synchronization
    #                   it is not set before the greenlet starts
    #                   it is None after the greenlet stops
    def __init__(self):
        self.parent = _current_
    def isactive(self):
        return getattr(self, 'lock', None) is not None
    def switch(self, target):
        previous = _current_._controller
        self.switch_no_wait(target)
        # wait until someone releases this thread's lock
        previous.lock.acquire()
    def switch_no_wait(self, target):
        # lock tricks: each greenlet has its own lock which is almost always
        # in 'acquired' state:
        # * the current greenlet runs with its lock acquired
        # * all other greenlets wait on their own lock's acquire() call
        global _current_
        try:
            while 1:
                _current_ = target
                lock = self.lock
                if lock is not None:
                    break
                target = self.parent
                self = target._controller
        except AttributeError:
            # start the new greenlet
            lock = self.lock = thread.allocate_lock()
            lock.acquire()
            thread.start_new_thread(self.run_thread, (target.run,))
        else:
            # release (re-enable) the target greenlet's thread
            lock.release()
    def run_thread(self, run):
        #print 'ENTERING', self
        global _passaround_
        exc, val, tb = _passaround_
        if exc is None:
            try:
                result = run(*val)
            except SystemExit, e:
                _passaround_ = None, (e,), None
            except:
                _passaround_ = sys.exc_info()
            else:
                _passaround_ = None, (result,), None
        self.lock = None
        #print 'LEAVING', self
        self.switch_no_wait(self.parent)
    def kill(self, target):
        # see comments in greenlet.c:green_dealloc()
        global _passaround_
        self._parent_ = _current_
        _passaround_ = SystemExit, None, None
        self.switch(target)
        exc, val, tb = _passaround_
        del _passaround_
        if exc is not None:
            if val is None:
                print >> sys.stderr, "Exception", "%s" % (exc,),
            else:
                print >> sys.stderr, "Exception", "%s: %s" % (exc, val),
            print >> sys.stderr, "in", self, "ignored"
_current_ = None
main = greenlet()
main._controller.lock = thread.allocate_lock()
main._controller.lock.acquire()
_current_ = main
def getcurrent():
    return _current_