| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- # The contents of this file are subject to the Python Software Foundation
- # License Version 2.3 (the License). You may not copy or use this file, in
- # either source code or executable form, except in compliance with the License.
- # You may obtain a copy of the License at http://www.python.org/license.
- #
- # Software distributed under the License is distributed on an AS IS basis,
- # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- # for the specific language governing rights and limitations under the
- # License.
- #
- # by Greg Hazel
- import greenlet
- from BTL import defer
- class GreenletWithDeferred(greenlet.greenlet):
- __slots__ = ['root', 'yielded_once', 'finished']
- def __init__(self, root, df, _f, *a, **kw):
- self.root = root
- self.yielded_once = False
- self.finished = False
- greenlet.greenlet.__init__(self,
- lambda : self.body(df, _f, *a, **kw))
- def body(self, df, _f, *a, **kw):
- try:
- v = _f(*a, **kw)
- except:
- self.finished = True
- df.errback(defer.Failure())
- else:
- self.finished = True
- df.callback(v)
- return df
- def switch(self, *a):
- g = greenlet.getcurrent()
- if (isinstance(g, GreenletWithDeferred) and
- g.finished and g.parent == self):
- # control will return to the parent anyway, and switching to it
- # causes a memory leak (greenlets don't participate in gc).
- if a:
- return a[0]
- return
- return greenlet.greenlet.switch(self, *a)
- def launch_coroutine(_f, *a, **kw):
- parent = greenlet.getcurrent()
- if isinstance(parent, GreenletWithDeferred):
- parent = parent.root
- df = defer.Deferred()
- g = GreenletWithDeferred(parent, df, _f, *a, **kw)
- g.switch()
- return df
- def coroutine(_f):
- def replacement(*a, **kw):
- return launch_coroutine(_f, *a, **kw)
- return replacement
- def like_yield(df):
- assert isinstance(df, defer.Deferred)
- if not df.called or df.paused:
- g = greenlet.getcurrent()
- assert isinstance(g, GreenletWithDeferred)
- df.addBoth(g.switch)
- if not g.yielded_once:
- g.yielded_once = True
- g = g.parent
- else:
- g = g.root
- while not df.called or df.paused:
- g.switch()
- assert df.called and not df.paused
- return df.getResult()
|