# (c) Copyright 2009. CodeWeavers, Inc.
import os
import threading
import cxutils
class Event(object):
"""We are not using threading.Event because it works by polling and is
not as fast as it could be.
"""
__fields__ = ['r_pipe', 'w_pipe', 'lock']
def __init__(self):
self.r_pipe, self.w_pipe = os.pipe()
self.lock = threading.Lock()
# This follows the naming in threading.Event which is not PEP8 compliant!
# pylint: disable=C0103
def isSet(self):
readable, _unused1, _unused2 = cxutils.select([self.r_pipe], [], [], 0)
return bool(readable)
def set(self):
if not self.isSet():
# Not strictly necessary, but we'd like to keep the number of
# unread bytes small
os.write(self.w_pipe, 'a')
def clear(self):
self.lock.acquire()
while self.isSet():
os.read(self.r_pipe, 1)
self.lock.release()
def wait(self, timeout=None):
if timeout is None:
cxutils.select([self.r_pipe], [], [])
else:
cxutils.select([self.r_pipe], [], [], timeout)
def __del__(self):
os.close(self.r_pipe)
os.close(self.w_pipe)
class AsyncResult(object):
"""Stores value and makes it possible to wait for it to be set."""
def __init__(self):
self.event = Event()
self.value = None
self.error = None
def set(self, value):
"""Sets the value and signals its arrival."""
self.value = value
self.event.set()
def set_error(self, error):
"""Set an exception to be raised when the value is requested."""
self.error = error
self.event.set()
def poll(self):
"""Returns the value if it is set, otherwise None."""
# pylint: disable=E0012,E0702,W0706
if self.error is not None:
raise self.error
return self.value
def get(self):
"""Waits for the value to be set and returns it."""
self.event.wait()
return self.poll()