Exemple #1
0
def _spawn_startup(cb, args, kw, cancel=None):
    try:
        greenlet.getcurrent().parent.switch()
        cancel = None
    finally:
        if cancel is not None:
            cancel()
    return cb(*args, **kw)
Exemple #2
0
def _spawn_startup(cb, args, kw, cancel=None):
    try:
        greenlet.getcurrent().parent.switch()
        cancel = None
    finally:
        if cancel is not None:
            cancel()
    return cb(*args, **kw)
 def _send_tasklet(self, *args):
     try:
         t = self._tasklet
     except AttributeError:
         t = self._tasklet = greenlet.greenlet(self._tasklet_loop)
         t.switch()
     if args:
         return t.switch((1, greenlet.getcurrent(), args))
     else:
         return t.switch((-1, greenlet.getcurrent(), args))
Exemple #4
0
def g_log(*args):
    import sys
    from eventlib.support import greenlets as greenlet
    g_id = id(greenlet.getcurrent())
    if g_id is None:
        if greenlet.getcurrent().parent is None:
            ident = 'greenlet-main'
        else:
            g_id = id(greenlet.getcurrent())
            if g_id < 0:
                g_id += 1 + ((sys.maxint + 1) << 1)
            ident = '%08X' % (g_id,)
    else:
        ident = 'greenlet-%d' % (g_id,)
    print >>sys.stderr, '[%s] %s' % (ident, ' '.join(map(str, args)))
Exemple #5
0
 def switch(self):
     cur = greenlet.getcurrent()
     assert cur is not self.greenlet, 'Cannot switch to MAINLOOP from MAINLOOP'
     switch_out = getattr(cur, 'switch_out', None)
     if switch_out is not None:
         try:
             switch_out()
         except:
             traceback.print_exception(*sys.exc_info())
     if self.greenlet.dead:
         self.greenlet = greenlet.greenlet(self.run)
     try:
         greenlet.getcurrent().parent = self.greenlet
     except ValueError:
         pass
     return self.greenlet.switch()
Exemple #6
0
 def switch(self):
     cur = greenlet.getcurrent()
     assert cur is not self.greenlet, 'Cannot switch to MAINLOOP from MAINLOOP'
     switch_out = getattr(cur, 'switch_out', None)
     if switch_out is not None:
         try:
             switch_out()
         except:
             traceback.print_exception(*sys.exc_info())
     if self.greenlet.dead:
         self.greenlet = greenlet.greenlet(self.run)
     try:
         greenlet.getcurrent().parent = self.greenlet
     except ValueError:
         pass
     return self.greenlet.switch()
Exemple #7
0
def sleep(seconds=0):
    """Yield control to another eligible coroutine until at least *seconds* have
    elapsed.

    *seconds* may be specified as an integer, or a float if fractional seconds
    are desired. Calling sleep with *seconds* of 0 is the canonical way of
    expressing a cooperative yield. For example, if one is looping over a
    large list performing an expensive calculation without calling any socket
    methods, it's a good idea to call ``sleep(0)`` occasionally; otherwise
    nothing else will run.
    """
    hub = get_hub()
    assert hub.greenlet is not greenlet.getcurrent(), 'do not call blocking functions from the mainloop'
    timer = hub.schedule_call(seconds, greenlet.getcurrent().switch)
    try:
        hub.switch()
    finally:
        timer.cancel()
Exemple #8
0
def trampoline(fd,
               read=None,
               write=None,
               timeout=None,
               timeout_exc=TimeoutError):
    """Suspend the current coroutine until the given socket object or file
    descriptor is ready to *read*, ready to *write*, or the specified
    *timeout* elapses, depending on arguments specified.

    To wait for *fd* to be ready to read, pass *read* ``=True``; ready to
    write, pass *write* ``=True``. To specify a timeout, pass the *timeout*
    argument in seconds.

    If the specified *timeout* elapses before the socket is ready to read or
    write, *timeout_exc* will be raised instead of ``trampoline()``
    returning normally.
    """
    t = None
    hub = get_hub()
    current = greenlet.getcurrent()
    assert hub.greenlet is not current, 'do not call blocking functions from the mainloop'
    fileno = getattr(fd, 'fileno', lambda: fd)()

    def _do_close(_d, error=None):
        if error is None:
            current.throw(socket.error(32, 'Broken pipe'))
        else:
            current.throw(getattr(error, 'value',
                                  error))  # XXX convert to socket.error

    def cb(d):
        current.switch()
        # with TwistedHub, descriptor is actually an object (socket_rwdescriptor) which stores
        # this callback. If this callback stores a reference to the socket instance (fd)
        # then descriptor has a reference to that instance. This makes socket not collected
        # after greenlet exit. Since nobody actually uses the results of this switch, I removed
        # fd from here. If it will be needed than an indirect reference which is discarded right
        # after the switch above should be used.

    if timeout is not None:
        t = hub.schedule_call(timeout, current.throw, timeout_exc)
    try:
        descriptor = hub.add_descriptor(fileno, read and cb, write and cb,
                                        _do_close)
        try:
            return hub.switch()
        finally:
            hub.remove_descriptor(descriptor)
    finally:
        if t is not None:
            t.cancel()
Exemple #9
0
def select(read_list, write_list, error_list, timeout=None):
    hub = get_hub()
    t = None
    current = greenlet.getcurrent()
    assert hub.greenlet is not current, 'do not call blocking functions from the mainloop'
    ds = {}
    for r in read_list:
        ds[get_fileno(r)] = {'read': r}
    for w in write_list:
        ds.setdefault(get_fileno(w), {})['write'] = w
    for e in error_list:
        ds.setdefault(get_fileno(e), {})['error'] = e

    descriptors = []

    def on_read(d):
        original = ds[get_fileno(d)]['read']
        current.switch(([original], [], []))

    def on_write(d):
        original = ds[get_fileno(d)]['write']
        current.switch(([], [original], []))

    def on_error(d, _err=None):
        original = ds[get_fileno(d)]['error']
        current.switch(([], [], [original]))

    def on_timeout():
        current.switch(([], [], []))

    if timeout is not None:
        t = hub.schedule_call(timeout, on_timeout)
    try:
        for k, v in list(ds.items()):
            d = hub.add_descriptor(k,
                                   v.get('read') is not None and on_read,
                                   v.get('write') is not None and on_write,
                                   v.get('error') is not None and on_error)
            descriptors.append(d)
        try:
            return hub.switch()
        finally:
            for d in descriptors:
                hub.remove_descriptor(d)
    finally:
        if t is not None:
            t.cancel()
Exemple #10
0
def select(read_list, write_list, error_list, timeout=None):
    hub = get_hub()
    t = None
    current = greenlet.getcurrent()
    assert hub.greenlet is not current, 'do not call blocking functions from the mainloop'
    ds = {}
    for r in read_list:
        ds[get_fileno(r)] = {'read' : r}
    for w in write_list:
        ds.setdefault(get_fileno(w), {})['write'] = w
    for e in error_list:
        ds.setdefault(get_fileno(e), {})['error'] = e

    descriptors = []

    def on_read(d):
        original = ds[get_fileno(d)]['read']
        current.switch(([original], [], []))

    def on_write(d):
        original = ds[get_fileno(d)]['write']
        current.switch(([], [original], []))

    def on_error(d, _err=None):
        original = ds[get_fileno(d)]['error']
        current.switch(([], [], [original]))

    def on_timeout():
        current.switch(([], [], []))

    if timeout is not None:
        t = hub.schedule_call(timeout, on_timeout)
    try:
        for k, v in ds.iteritems():
            d = hub.add_descriptor(k,
                                   v.get('read') is not None and on_read,
                                   v.get('write') is not None and on_write,
                                   v.get('error') is not None and on_error)
            descriptors.append(d)
        try:
            return hub.switch()
        finally:
            for d in descriptors:
                hub.remove_descriptor(d)
    finally:
        if t is not None:
            t.cancel()
Exemple #11
0
def trampoline(fd, read=None, write=None, timeout=None, timeout_exc=TimeoutError):
    """Suspend the current coroutine until the given socket object or file
    descriptor is ready to *read*, ready to *write*, or the specified
    *timeout* elapses, depending on arguments specified.

    To wait for *fd* to be ready to read, pass *read* ``=True``; ready to
    write, pass *write* ``=True``. To specify a timeout, pass the *timeout*
    argument in seconds.

    If the specified *timeout* elapses before the socket is ready to read or
    write, *timeout_exc* will be raised instead of ``trampoline()``
    returning normally.
    """
    t = None
    hub = get_hub()
    current = greenlet.getcurrent()
    assert hub.greenlet is not current, 'do not call blocking functions from the mainloop'
    fileno = getattr(fd, 'fileno', lambda: fd)()
    def _do_close(_d, error=None):
        if error is None:
            current.throw(socket.error(32, 'Broken pipe'))
        else:
            current.throw(getattr(error, 'value', error)) # XXX convert to socket.error
    def cb(d):
        current.switch()
        # with TwistedHub, descriptor is actually an object (socket_rwdescriptor) which stores
        # this callback. If this callback stores a reference to the socket instance (fd)
        # then descriptor has a reference to that instance. This makes socket not collected
        # after greenlet exit. Since nobody actually uses the results of this switch, I removed
        # fd from here. If it will be needed than an indirect reference which is discarded right
        # after the switch above should be used.
    if timeout is not None:
        t = hub.schedule_call(timeout, current.throw, timeout_exc)
    try:
        descriptor = hub.add_descriptor(fileno, read and cb, write and cb, _do_close)
        try:
            return hub.switch()
        finally:
            hub.remove_descriptor(descriptor)
    finally:
        if t is not None:
            t.cancel()
    def _tasklet_loop(self):
        deque = self.deque = collections.deque()
        hub = api.get_hub()
        current = greenlet.getcurrent()

        def switch(g, value=None, exc=None):
            if exc is None:
                return g.switch(value)
            else:
                return g.throw(exc)

        direction, caller, args = switch(current.parent or current)
        try:
            while True:
                if direction == -1:
                    # waiting to receive
                    if self.balance > 0:
                        sender, args = deque.popleft()
                        hub.schedule_call(0, switch, sender)
                        hub.schedule_call(0, switch, caller, *args)
                    else:
                        deque.append(caller)
                else:
                    # waiting to send
                    if self.balance < 0:
                        receiver = deque.popleft()
                        hub.schedule_call(0, switch, receiver, *args)
                        hub.schedule_call(0, switch, caller)
                    else:
                        deque.append((caller, args))
                self.balance += direction
                direction, caller, args = hub.switch()
        finally:
            deque.clear()
            del self.deque
            self.balance = 0
Exemple #13
0
 def stop(self):
     self.abort()
     if self.greenlet is not greenlet.getcurrent():
         self.switch()
Exemple #14
0
def get_ident(gr=None):
    if gr is None:
        return id(greenlet.getcurrent())
    else:
        return id(gr)
Exemple #15
0
def _spawn(g):
    g.parent = greenlet.getcurrent()
    g.switch()
Exemple #16
0
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""Integrate eventlib with twisted's reactor mainloop.

You generally don't have to use it unless you need to call reactor.run()
yourself.
"""
from eventlib.hubs.twistedr import BaseTwistedHub
from eventlib.api import use_hub, _threadlocal
from eventlib.support import greenlets as greenlet

use_hub(BaseTwistedHub)
if hasattr(_threadlocal, 'hub'):
    raise RuntimeError('the current thread already has a hub')
hub = _threadlocal.hub = _threadlocal.Hub(greenlet.getcurrent())
Exemple #17
0
def _spawn(g):
    g.parent = greenlet.getcurrent()
    g.switch()
Exemple #18
0
 def stop(self):
     self.abort()
     if self.greenlet is not greenlet.getcurrent():
         self.switch()
Exemple #19
0
def get_ident(gr=None):
    if gr is None:
        return id(greenlet.getcurrent())
    else:
        return id(gr)
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

"""Integrate eventlib with twisted's reactor mainloop.

You generally don't have to use it unless you need to call reactor.run()
yourself.
"""
from eventlib.hubs.twistedr import BaseTwistedHub
from eventlib.api import use_hub, _threadlocal
from eventlib.support import greenlets as greenlet

use_hub(BaseTwistedHub)
if hasattr(_threadlocal, 'hub'):
    raise RuntimeError('the current thread already has a hub')
hub = _threadlocal.hub = _threadlocal.Hub(greenlet.getcurrent())