# speed test
from __future__ import generators
import time, sys

class StacklessError(Exception): pass

try:
    from stackless import *
    IS_SLP = True
except ImportError:
    IS_SLP = False
    print "This is not Stackless Python. Most tests will not work."
    def schedule(*args):
        raise StacklessError
    test_outside = test_cframe = test_cframe_nr = schedule
    def enable_softswitch(n): pass
    class stackless:
        debug = 0 # assume to be tested with normal Python
    tasklist = []
    class tasklet(object):
        def __init__(self, func):
            self.func = func
            tasklist.append(self)
        def __call__(self, *args):
            self.args = args
        def run(self):
            self.func(*self.args)
    def run():
        global tasklist
        try:
            for each in tasklist:
                each.run()
        finally:
            tasklist = []

print sys.version

args_given = None
try:
    args_given = int(sys.argv[1])
except: pass

def check():
    cur = stackless.current
    ret = [hex(id(cur))]
    frame = cur.frame
    import sys
    g = sys.getrefcount
    while frame:
        ret.append('  ')
        ret.append(hex(id(frame)))
        ret.append(str(g(frame) - 1))
        frame = frame.f_back
    return ' '.join(ret)

def f(n, sched):
    print 'enter', check()
    sched();
    print 'leave'#, check()
    1 << 17
        
def tester(func, niter, args, msg, ntasks=2, run=run):
    print "%8d %s" % (niter, msg, ),
    clock = time.clock
    args = (niter / ntasks,) + args
    diff = 0
    for i in range(ntasks):
        tasklet(func)(*args)
    try:
        start = clock()
        run()
        diff = clock() - start
        if diff == 0:
            print 'no timing possible'
        else:
            print "took %9.5f seconds, rate = %10d/s" % (diff, niter/diff)
    except StacklessError:
        print "could not run, this is not Stackless"
    return diff

# generator test
def gf(n):
    for i in xrange(0, n, 20):
        yield i; yield i; yield i; yield i; yield i
        yield i; yield i; yield i; yield i; yield i
        yield i; yield i; yield i; yield i; yield i
        yield i; yield i; yield i; yield i; yield i

def gentest(n):
    for i in gf(n):pass

niter = 10000000

if stackless.debug:
    niter = 10
    
if args_given:
    niter = args_given

def schedule_cb(prev, next):
    s = '%s %r %s %r' % ('prev', prev, 'next', next)
    print s

##stackless.set_schedule_callback(schedule_cb)

enable_softswitch(0)
res = []
niter = 2
res.append(tester(test_cframe, niter, (),      "cframe switches    "))
##res.append(tester(test_cframe, niter//10, (),  "cframe from outside", 1, test_outside))
##res.append(tester(f, niter, (schedule,),       "frame switches     "))
