Source

aurum / python / aurum / repeatedcmd.py

from multiprocessing import Process, Queue, Value
from aurum.utils import readsystem
import time

class ProcessHaltedError(Exception):
    pass

class RepeatedCmd(object):
    __slots__ = set(('interval', 'func', 'timer', 'value'))
    def __init__(self, interval, func, *args, **kwargs):
        self.interval = Value('f', float(interval))
        self.queue    = Queue()
        self.func     = func
        def procfunc(queue, interval, func, args, kwargs):
            while True:
                value = func(*args, **kwargs)
                while(not queue.empty()):
                    queue.get()
                queue.put(value)
                time.sleep(interval.value)
        self.process  = Process(target=procfunc,
                                args=(self.queue, self.interval, func, args, kwargs))
        self.process.start()
        self.value = None

    def setinterval(self, interval):
        if not self.process.is_alive():
            raise ProcessHaltedError('Child process is not alive')
        self.interval.value = float(interval)

    def getvalue(self):
        if not self.process.is_alive():
            raise ProcessHaltedError('Child process is not alive')
        if self.value is None or not self.queue.empty():
            while(not self.queue.empty()):
                self.value = self.queue.get()
        return self.value

    def getcurrentvalue(self):
        self.value = self.func()
        return self.value

    def stop(self):
        if not self.process.is_alive():
            raise ProcessHaltedError('Child process is not alive')
        self.process.terminate()

    __del__ = stop

processes={}

thcount=0

def new(*args, **kwargs):
    global thcount
    global processes
    rcid=thcount
    thcount+=1
    processes[rcid]=RepeatedCmd(*args, **kwargs)
    return rcid

def get(rcid):
    global processes
    return processes[rcid].getvalue()

def remove(rcid):
    global processes
    thread=processes.pop(rcid)
    thread.stop()