def fmain(seen): try: greenstack.getcurrent().parent.switch() except: seen.append(sys.exc_info()[0]) raise raise SomeError
def fthread(): lock2.acquire() greenstack.getcurrent() del g[0] lock1.release() lock2.acquire() greenstack.getcurrent() lock1.release()
def worker(): try: # Wait to be killed main.switch() except greenstack.GreenstackExit: # Resurrect and switch to parent result.append(greenstack.getcurrent().parent) result.append(greenstack.getcurrent()) hub.switch()
def worker(): # wait for the value value = greenstack.getcurrent().parent.switch() # delete all references to ourself del worker[0] initiator.parent = greenstack.getcurrent().parent # switch to main with the value, but because # ts_current is the last reference to us we # return immediately try: greenstack.getcurrent().parent.switch(value) finally: seen.append(greenstack.getcurrent())
def __next__(self): self.parent = greenstack.getcurrent() result = self.switch() if self: return result else: raise StopIteration
def Yield(value): g = greenstack.getcurrent() while not isinstance(g, genlet): if g is None: raise RuntimeError('yield outside a genlet') g = g.parent g.parent.switch(value)
def test_threaded_updatecurrent(self): # released when main thread should execute lock1 = threading.Lock() lock1.acquire() # released when another thread should execute lock2 = threading.Lock() lock2.acquire() class finalized(object): def __del__(self): # happens while in green_updatecurrent() in main greenstack # should be very careful not to accidentally call it again # at the same time we must make sure another thread executes lock2.release() lock1.acquire() # now ts_current belongs to another thread def deallocator(): greenstack.getcurrent().parent.switch() def fthread(): lock2.acquire() greenstack.getcurrent() del g[0] lock1.release() lock2.acquire() greenstack.getcurrent() lock1.release() main = greenstack.getcurrent() g = [greenstack(deallocator)] g[0].bomb = finalized() g[0].switch() t = threading.Thread(target=fthread) t.start() # let another thread grab ts_current and deallocate g[0] lock2.release() lock1.acquire() # this is the corner stone # getcurrent() will notice that ts_current belongs to another thread # and start the update process, which would notice that g[0] should # be deallocated, and that will execute an object's finalizer. Now, # that object will let another thread run so it can grab ts_current # again, which would likely crash the interpreter if there's no # check for this case at the end of green_updatecurrent(). This test # passes if getcurrent() returns correct result, but it's likely # to randomly crash if it's not anyway. self.assertEqual(greenstack.getcurrent(), main) # wait for another thread to complete, just in case t.join()
def Yield(value, level=1): g = greenstack.getcurrent() while level != 0: if not isinstance(g, genlet): raise RuntimeError('yield outside a genlet') if level > 1: g.parent.set_child(g) g = g.parent level -= 1 g.switch(value)
def __next__(self): if self.child: child = self.child while child.child: tmp = child child = child.child tmp.child = None result = child.switch() else: self.parent = greenstack.getcurrent() result = self.switch() if self: return result else: raise StopIteration
def attempt(): lock1 = threading.Lock() lock1.acquire() lock2 = threading.Lock() lock2.acquire() recycled = [False] def another_thread(): lock1.acquire() # wait for gc greenstack.getcurrent() # update ts_current lock2.release() # release gc t = threading.Thread(target=another_thread) t.start() class gc_callback(object): def __del__(self): lock1.release() lock2.acquire() recycled[0] = True class garbage(object): def __init__(self): self.cycle = self self.callback = gc_callback() l = [] x = range(N*2) current = greenstack.getcurrent() g = garbage() for i in x: g = None # lose reference to garbage if recycled[0]: # gc callback called prematurely t.join() return False last = greenstack() if recycled[0]: break # yes! gc called in green_new l.append(last) # increase allocation counter else: # gc callback not called when expected gc.collect() if recycled[0]: t.join() return False self.assertEqual(last.parent, current) for g in l: self.assertEqual(g.parent, current) return True
def test_parent_restored_on_kill(self): hub = greenstack(lambda: None) main = greenstack.getcurrent() result = [] def worker(): try: # Wait to be killed main.switch() except greenstack.GreenstackExit: # Resurrect and switch to parent result.append(greenstack.getcurrent().parent) result.append(greenstack.getcurrent()) hub.switch() g = greenstack(worker, parent=hub) g.switch() del g self.assertTrue(result) self.assertEqual(result[0], main) self.assertEqual(result[1].parent, hub)
def test_throw_goes_to_original_parent(self): main = greenstack.getcurrent() def f1(): try: main.switch("f1 ready to catch") except IndexError: return "caught" else: return "normal exit" def f2(): main.switch("from f2") g1 = greenstack(f1) g2 = greenstack(f2, parent=g1) self.assertRaises(IndexError, g2.throw, IndexError) self.assertTrue(g2.dead) self.assertTrue(g1.dead) g1 = greenstack(f1) g2 = greenstack(f2, parent=g1) res = g1.switch() self.assertEqual(res, "f1 ready to catch") res = g2.throw(IndexError) self.assertEqual(res, "caught") self.assertTrue(g2.dead) self.assertTrue(g1.dead) g1 = greenstack(f1) g2 = greenstack(f2, parent=g1) res = g1.switch() self.assertEqual(res, "f1 ready to catch") res = g2.switch() self.assertEqual(res, "from f2") res = g2.throw(IndexError) self.assertEqual(res, "caught") self.assertTrue(g2.dead) self.assertTrue(g1.dead)
def f(): lst.append(1) greenstack.getcurrent().parent.switch()
def another_thread(): lock1.acquire() # wait for gc greenstack.getcurrent() # update ts_current lock2.release() # release gc
def switchapply(): apply(greenstack.getcurrent().parent.switch, args, kwargs)
def __len__(self): greenstack.getcurrent().switch() return tuple.__len__(self)
def f1(): f = sys._getframe(0) self.assertEqual(f.f_back, None) greenstack.getcurrent().parent.switch(f) return "meaning of life"
def foo(x): greenstack.getcurrent().parent.switch(x=x) greenstack.getcurrent().parent.switch(2, x=3) return x, x ** 2
def f(): greenstack.getcurrent().test = 42
def worker(): greenstack.getcurrent().parent.switch()
def blank(): greenstack.getcurrent().parent.switch()
def deallocator(): greenstack.getcurrent().parent.switch()
def switch(*args): return greenstack.getcurrent().parent.switch(*args)