class UnitWorker(object): def __init__(self, name): super(UnitWorker,self).__init__() self.name = name self.scan = IOScanListThread() self.scan.force = 0 self.worker = Worker() addHook('AfterIocRunning', self.worker.start) addHook('AtIocExit', self.worker.join) def add(self, rec, unit, val): self.worker.add(self.update, (rec, unit, val)) def update(self, rec, unit, val): F, _ = _fns[unit] V = F(val) values = {} for U,(F,R) in _fns.iteritems(): values[U] = R(V) self.scan.interrupt(reason=values)
def getworker(cls): with cls._worker_lock: if cls._worker is not None: return cls._worker import devsup.hooks T = Worker(max=cls.queuelength) devsup.hooks.addHook('AtIocExit', T.join) T.start() cls._worker = T return T
def __init__(self, name): super(UnitWorker,self).__init__() self.name = name self.scan = IOScanListThread() self.scan.force = 0 self.worker = Worker() addHook('AfterIocRunning', self.worker.start) addHook('AtIocExit', self.worker.join)
def __init__(self, rec, link): self.rec, self.link = rec, link if self.worker is None: from devsup.util import Worker self.worker = Worker(max=1) @initHook('AtIocExit') def _exit(): print 'stop worker for', rec.NAME self.worker.join() self.worker.start() assert self.worker is not None, "Offload requires a worker thread" I = [] for fld, name in self.inputs.items(): F = rec.field(fld) I.append((fld, name, F.fieldinfo()[2] != 1)) O = list(self.outputs.items()) self._inputs, self._outputs = I, O
def __init__(self, rec, link): self.rec, self.link = rec, link if self.worker is None: from devsup.util import Worker self.worker = Worker(max=1) @initHook('AtIocExit') def _exit(): print 'stop worker for', rec.NAME self.worker.join() self.worker.start() assert self.worker is not None, "Offload requires a worker thread" I = [] for fld,name in self.inputs.items(): F = rec.field(fld) I.append((fld, name, F.fieldinfo()[2]!=1)) O = list(self.outputs.items()) self._inputs, self._outputs = I, O
class AsyncOffload(object): """A device support which off-loads processing to a worker thread. >>> class ArrSum(AsyncOffload): inputs = {'A':'one', 'B':'two'} outputs= {'VALA':'result'} def inThread(one=0, two=0): return {'result':one+two} The attribute "worker" may be set to an instance of Worker, either statically, or in the derived class constructor (before calling the Base class constructor). If this attribute remains None, then a new Worker thread is created for each record instance. The attribute "scan" may similarly be set to an instance of IOScanListBlock. The "inputs" and "outputs" dictionary exist to map record Field names to internal names. This also serves to indicate which fields the inThread methods may use. This avoid processing of unnecesary (array) fields. """ worker = None scan = None inputs = {} outputs = {} timefld = None def __init__(self, rec, link): self.rec, self.link = rec, link if self.worker is None: from devsup.util import Worker self.worker = Worker(max=1) @initHook('AtIocExit') def _exit(): print 'stop worker for', rec.NAME self.worker.join() self.worker.start() assert self.worker is not None, "Offload requires a worker thread" I = [] for fld, name in self.inputs.items(): F = rec.field(fld) I.append((fld, name, F.fieldinfo()[2] != 1)) O = list(self.outputs.items()) self._inputs, self._outputs = I, O def allowScan(self, rec): if self.scan: return self.scan.add(rec) def detach(self, rec): pass def process(self, rec, reason=None): if reason is None: self._tstart = time.time() V = {} for fld, name, arr in self._inputs: val = getattr(rec, fld) if arr: val = val.copy() V[name] = val self.worker.add(self._wrap, args=(rec, ), kws=V) rec.asyncStart() else: result = reason if result['ok']: for fld, name in self._outputs: setattr(rec, fld, result.get(name, 0)) sevr = result.get('severity', 0) if sevr: rec.setSevr(sevr) else: rec.setSevr() self._tend = time.time() if self.timefld: setattr(rec, self.timefld, self._tend - self._tstart) def _wrap(self, rec, **kws): try: result = self.inThread(**kws) result.setdefault('ok', True) rec.asyncFinish(reason=result) except: _log.exception('Error while processing %s', rec.NAME) rec.asyncFinish(reason={'ok': False}) def inThread(self, **kws): return {'ok': False}
class AsyncOffload(object): """A device support which off-loads processing to a worker thread. >>> class ArrSum(AsyncOffload): inputs = {'A':'one', 'B':'two'} outputs= {'VALA':'result'} def inThread(one=0, two=0): return {'result':one+two} The attribute "worker" may be set to an instance of Worker, either statically, or in the derived class constructor (before calling the Base class constructor). If this attribute remains None, then a new Worker thread is created for each record instance. The attribute "scan" may similarly be set to an instance of IOScanListBlock. The "inputs" and "outputs" dictionary exist to map record Field names to internal names. This also serves to indicate which fields the inThread methods may use. This avoid processing of unnecesary (array) fields. """ worker = None scan = None inputs = {} outputs = {} timefld = None def __init__(self, rec, link): self.rec, self.link = rec, link if self.worker is None: from devsup.util import Worker self.worker = Worker(max=1) @initHook('AtIocExit') def _exit(): print 'stop worker for', rec.NAME self.worker.join() self.worker.start() assert self.worker is not None, "Offload requires a worker thread" I = [] for fld,name in self.inputs.items(): F = rec.field(fld) I.append((fld, name, F.fieldinfo()[2]!=1)) O = list(self.outputs.items()) self._inputs, self._outputs = I, O def allowScan(self, rec): if self.scan: return self.scan.add(rec) def detach(self, rec): pass def process(self, rec, reason=None): if reason is None: self._tstart = time.time() V = {} for fld,name,arr in self._inputs: val = getattr(rec, fld) if arr: val = val.copy() V[name] = val self.worker.add(self._wrap, args=(rec,), kws=V) rec.asyncStart() else: result = reason if result['ok']: for fld,name in self._outputs: setattr(rec, fld, result.get(name, 0)) sevr = result.get('severity', 0) if sevr: rec.setSevr(sevr) else: rec.setSevr() self._tend = time.time() if self.timefld: setattr(rec, self.timefld, self._tend-self._tstart) def _wrap(self, rec, **kws): try: result = self.inThread(**kws) result.setdefault('ok', True) rec.asyncFinish(reason=result) except: _log.exception('Error while processing %s', rec.NAME) rec.asyncFinish(reason={'ok':False}) def inThread(self, **kws): return {'ok':False}