def test_event_clear(self): ev = Event() def waiter(): self.assertTrue(ev.wait()) ev.clear() evergreen.spawn(waiter) evergreen.spawn(ev.set) self.loop.run() self.assertFalse(ev.is_set())
def test_event_kill_waiter(self): ev = Event() def waiter(): ev.wait() t1 = evergreen.spawn(waiter) evergreen.spawn(t1.kill) evergreen.spawn(ev.set) self.loop.run() self.assertTrue(ev.is_set())
class Result(object): def __init__(self): self._event = Event() self._result = None self._exception = None self._used = False def is_set(self): return self._event.is_set() def set_result(self, value): if self.is_set(): raise RuntimeError('already set') self._result = value self._event.set() def set_exception(self, exc): if self.is_set(): raise RuntimeError('already set') self._exception = exc self._event.set() def wait(self, timeout=None): if self._used: raise RuntimeError('already used, clear it in order to use it again') self._event.wait(timeout) try: if self.is_set(): return self._get_result() return None finally: self._result = self._exception = None def clear(self): self._event.clear() self._result = None self._exception = None self._used = False def _get_result(self): self._used = True if self._exception is not None: six.reraise(type(self._exception), self._exception) else: return self._result
class Result(object): def __init__(self): self._event = Event() self._result = None self._exception = None self._used = False def is_set(self): return self._event.is_set() def set_result(self, value): if self.is_set(): raise RuntimeError('already set') self._result = value self._event.set() def set_exception(self, exc): if self.is_set(): raise RuntimeError('already set') self._exception = exc self._event.set() def wait(self, timeout=None): if self._used: raise RuntimeError( 'already used, clear it in order to use it again') self._event.wait(timeout) try: if self.is_set(): return self._get_result() return None finally: self._result = self._exception = None def clear(self): self._event.clear() self._result = None self._exception = None self._used = False def _get_result(self): self._used = True if self._exception is not None: six.reraise(type(self._exception), self._exception) else: return self._result
class Task(tasklet): def __init__(self, target=None, name=None, args=(), kwargs={}): super(Task, self).__init__(parent=evergreen.current.loop.tasklet) self._name = str(name or _newname()) self._target = target self._args = args self._kwargs = kwargs self._started = False self._exit_event = Event() def start(self): if self._started: raise RuntimeError('tasks can only be started once') self._started = True evergreen.current.loop.call_soon(self.switch) def run_(self): if self._target: self._target(*self._args, **self._kwargs) def join(self, timeout=None): """Wait for this Task to end. If a timeout is given, after the time expires the function will return anyway.""" return self._exit_event.wait(timeout) def kill(self, *throw_args): """Terminates the current task by raising an exception into it. Whatever that task might be doing; be it waiting for I/O or another primitive, it sees an exception as soon as it yields control. By default, this exception is TaskExit, but a specific exception may be specified. *throw_args* should be the same as the arguments to raise; either an exception instance or an exc_info tuple. """ if self.dead: return if not self: # task hasn't started yet and therefore throw won't work def just_raise(*a, **kw): try: if throw_args: six.reraise(throw_args[0], throw_args[1], throw_args[2]) else: raise TaskExit() finally: self._exit_event.set() self.run_ = just_raise return evergreen.current.loop.call_soon(self.throw, *throw_args) def __repr__(self): status = "initial" if self._started: status = "started" if self.dead: status = "dead" if self._exit_event.is_set(): status = "ended" return "<%s(%s, %s)>" % (self.__class__.__name__, self._name, status) @property def name(self): return self._name # internal def switch(self, *args, **kwargs): current = evergreen.current.task if current is not evergreen.current.loop.tasklet: raise RuntimeError('only the loop tasklet can switch to a Task') return super(Task, self).switch(*args, **kwargs) def throw(self, *args): current = evergreen.current.task if current is not evergreen.current.loop.tasklet: raise RuntimeError('only the loop tasklet can throw to a Task') return super(Task, self).throw(*args) def run(self): try: self.run_() finally: del self._target, self._args, self._kwargs self._exit_event.set()
class Task(Fiber): def __init__(self, target=None, name=None, args=(), kwargs={}): super(Task, self).__init__(target=self.__run, parent=evergreen.current.loop.task) self._name = str(name or _newname()) self._target = target self._args = args self._kwargs = kwargs self._started = False self._running = False self._exit_event = Event() def start(self): if self._started: raise RuntimeError('tasks can only be started once') self._started = True evergreen.current.loop.call_soon(self.switch) def run(self): if self._target: self._target(*self._args, **self._kwargs) def join(self, timeout=None): """Wait for this Task to end. If a timeout is given, after the time expires the function will return anyway.""" if not self._started: raise RuntimeError('cannot join task before it is started') return self._exit_event.wait(timeout) def kill(self, typ=TaskExit, value=None, tb=None): """Terminates the current task by raising an exception into it. Whatever that task might be doing; be it waiting for I/O or another primitive, it sees an exception as soon as it yields control. By default, this exception is TaskExit, but a specific exception may be specified. """ if not self.is_alive(): return if not value: value = typ() if not self._running: # task hasn't started yet and therefore throw won't work def just_raise(): six.reraise(typ, value, tb) self.run = just_raise return evergreen.current.loop.call_soon(self.throw, typ, value, tb) def __repr__(self): status = "initial" if self._started: status = "started" if self._running: status = "running" if self._exit_event.is_set(): status = "ended" return "<%s(%s, %s)>" % (self.__class__.__name__, self._name, status) @property def name(self): return self._name # internal def __run(self): try: self._running = True self.run() except TaskExit: pass finally: self._running = False del self._target, self._args, self._kwargs self._exit_event.set()