def foo(): try: greenstack.getcurrent().parent.switch() except ValueError: seen.append(sys.exc_info()[1]) except greenstack.GreenstackExit: raise AssertionError
def worker(): # main and additional *finished* greenstacks ll = greenstack.getcurrent().ll = [] def additional(): ll.append(greenstack.getcurrent()) for i in range(2): greenstack.greenstack(additional).switch() gg.append(weakref.ref(greenstack.getcurrent()))
def bar(): greenstack.getcurrent().parent.switch() # This final switch should go back to the main greenstack, since # the test_setparent() function in the C extension should have # reparented this greenstack. greenstack.getcurrent().parent.switch() raise AssertionError("Should never have reached this code")
def test_kwarg_refs(self): kwargs = {} g = greenstack.greenstack( lambda **kwargs: greenstack.getcurrent().parent.switch(**kwargs)) for i in range(100): g.switch(**kwargs) self.assertEqual(sys.getrefcount(kwargs), 2)
def test_greenstack_tracing(self): main = greenstack.getcurrent() actions = [] def trace(*args): actions.append(args) def dummy(): pass def dummyexc(): raise SomeError() oldtrace = greenstack.settrace(trace) try: g1 = greenstack.greenstack(dummy) g1.switch() g2 = greenstack.greenstack(dummyexc) self.assertRaises(SomeError, g2.switch) finally: greenstack.settrace(oldtrace) self.assertEqual(actions, [ ('switch', (main, g1)), ('switch', (g1, main)), ('switch', (main, g2)), ('throw', (g2, main)), ])
def chain(n): start_node = greenstack.getcurrent() for i in xrange(n): g = greenstack.greenstack(link) g.switch(start_node) start_node = g return start_node.switch(0)
def test_arg_refs(self): args = ('a', 'b', 'c') refcount_before = sys.getrefcount(args) g = greenstack.greenstack( lambda *args: greenstack.getcurrent().parent.switch(*args)) for i in range(100): g.switch(*args) self.assertEqual(sys.getrefcount(args), refcount_before)
def switcher(n): while True: if greenstack.getcurrent() == switcher1: n = switcher2.switch(n) else: n = switcher1.switch(n) n -= 1 if n == 0: return
def test_finalizer_crash(self): # This test is designed to crash when active greenstacks # are made garbage collectable, until the underlying # problem is resolved. How does it work: # - order of object creation is important # - array is created first, so it is moved to unreachable first # - we create a cycle between a greenstack and this array # - we create an object that participates in gc, is only # referenced by a greenstack, and would corrupt gc lists # on destruction, the easiest is to use an object with # a finalizer # - because array is the first object in unreachable it is # cleared first, which causes all references to greenstack # to disappear and causes greenstack to be destroyed, but since # it is still live it causes a switch during gc, which causes # an object with finalizer to be destroyed, which causes stack # corruption and then a crash class object_with_finalizer(object): def __del__(self): pass array = [] parent = greenstack.getcurrent() def greenstack_body(): greenstack.getcurrent().object = object_with_finalizer() try: parent.switch() finally: del greenstack.getcurrent().object g = greenstack.greenstack(greenstack_body) g.array = array array.append(g) g.switch() del array del g greenstack.getcurrent() gc.collect()
def test_exception_disables_tracing(self): main = greenstack.getcurrent() actions = [] def trace(*args): actions.append(args) raise SomeError() def dummy(): main.switch() g = greenstack.greenstack(dummy) g.switch() oldtrace = greenstack.settrace(trace) try: self.assertRaises(SomeError, g.switch) self.assertEqual(greenstack.gettrace(), None) finally: greenstack.settrace(oldtrace) self.assertEqual(actions, [ ('switch', (main, g)), ])
def test_threaded_leak(self): gg = [] def worker(): # only main greenstack present gg.append(weakref.ref(greenstack.getcurrent())) for i in range(2): t = threading.Thread(target=worker) t.start() t.join() del t greenstack.getcurrent() # update ts_current self.recycle_threads() greenstack.getcurrent() # update ts_current gc.collect() greenstack.getcurrent() # update ts_current for g in gg: self.assertTrue(g() is None)
def test_threaded_adv_leak(self): gg = [] def worker(): # main and additional *finished* greenstacks ll = greenstack.getcurrent().ll = [] def additional(): ll.append(greenstack.getcurrent()) for i in range(2): greenstack.greenstack(additional).switch() gg.append(weakref.ref(greenstack.getcurrent())) for i in range(2): t = threading.Thread(target=worker) t.start() t.join() del t greenstack.getcurrent() # update ts_current self.recycle_threads() greenstack.getcurrent() # update ts_current gc.collect() greenstack.getcurrent() # update ts_current for g in gg: self.assertTrue(g() is None)
def greenstack_body(): greenstack.getcurrent().object = object_with_finalizer() try: parent.switch() finally: del greenstack.getcurrent().object
def worker(): # only main greenstack present gg.append(weakref.ref(greenstack.getcurrent()))
def worker(): try: greenstack.getcurrent().parent.switch() finally: seen.append(g())
def additional(): ll.append(greenstack.getcurrent())
def link(next_greenstack): value = greenstack.getcurrent().parent.switch() next_greenstack.switch(value + 1)
#!/usr/bin/env python import greenstack from time import clock main = greenstack.getcurrent() num_links = 100000 def link(value): if value == num_links: print 'Result:' return; g = greenstack.greenstack(link) g.parent = main g.switch(value + 1) start_time = clock() link(0) print clock() - start_time, 'seconds'