Source

nsocket / nsocket / core / cothread.py

Full commit
import sys
import greenlet
import threading 
import itertools

_local = threading.local

def _execute(func, args, kwargs):
    
    threads = getattr(_local, 'threads', None)
    if not threads:
        threads = _local.threads = {}
        _local.counter = itertools.count(1)
    
    current = greenlet.getcurrent()
    id = _local.counter.next()
    threads[current] = {'id':id}
    try:
        return func(*args, **kwargs)
    finally:
        threads.pop(current, None)

def create(target=_execute):
    return greenlet.greenlet(target)

def getcurrent():
    return greenlet.getcurrent()

def switch(other=None, value=None):

    current = greenlet.getcurrent()
    if other is None:
        other = current.parent
    if other is None:
        other = current
    try:
        ret = other.switch(value)
        res, exc = ret, None
    except:
        res, exc = None, sys.exc_info()
    
    if isinstance(exc, tuple):
        typ, exc, tb = exc
        raise typ, exc, tb
    elif exc is not None:
        raise exc
    
    return ret

def _startup_engine(cb, args, kw, cancel=None):
    try:
        switch(greenlet.getcurrent().parent)
    finally:
        if not cancel:
            return  cb(*args, **kwargs)

def _spawn(g):
    switch(g)

def start_thread(function, *args, **kwargs):
    from nsocket.core.engine import engine
    g = create()
    
    g.parent = engine.thread
    t = engine.schedule(0, _spawn, g)
    switch(g, (_startup_engine, function, args, kwargs, t.cancel))
    return g
    
def threaded(func, *args, **kwargs):
    """
    co-thread decorator
    """
    def call(*arg, **kw):
        start_thread(func, *arg, **kw)
    return call