rework polling

Readable/Moveable can't be busy....

Change-Id: Icfe250e16dd30646cf3081f4850a8bacaa77a935
Reviewed-on: https://forge.frm2.tum.de/review/17859
Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de>
Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
Enrico Faulhaber
2018-04-26 16:25:02 +02:00
parent f0ea4bd9b8
commit 927ca854a2

View File

@ -21,6 +21,8 @@
# *****************************************************************************
"""Define Baseclasses for real Modules implemented in the server"""
from __future__ import print_function
# XXX: connect with 'protocol'-Modules.
# Idea: every Module defined herein is also a 'protocol'-Module,
# all others MUST derive from those, the 'interface'-class is still derived
@ -59,15 +61,23 @@ from secop.datatypes import DataType, EnumType, TupleOf, StringType, FloatRange,
EVENT_ONLY_ON_CHANGED_VALUES = False
# storage for Parameter settings:
# if readonly is False, the value can be changed (by code, or remote)
# if no default is given, the parameter MUST be specified in the configfile
# during startup, value is initialized with the default value or
# from the config file if specified there
class Param(object):
"""storage for Parameter settings + value + qualifiers
if readonly is False, the value can be changed (by code, or remote)
if no default is given, the parameter MUST be specified in the configfile
during startup, value is initialized with the default value or
from the config file if specified there
poll can be:
- False (never poll this parameter)
- True (poll this ever pollinterval)
- positive int (poll every N(th) pollinterval)
- negative int (normally poll every N(th) pollinterval, if module is busy, poll every pollinterval)
note: Drivable (and derived classes) poll with 10 fold frequency if module is busy....
"""
def __init__(self,
description,
datatype=None,
@ -432,6 +442,7 @@ class Module(object):
mkthread(self.late_init)
def late_init(self):
# this runs async somewhen after init
self.log.debug('late init()')
@ -463,45 +474,37 @@ class Readable(Module):
self._pollthread = mkthread(self.__pollThread)
def __pollThread(self):
try:
self.__pollThread_inner()
except Exception as e:
self.log.exception(e)
print(formatExtendedStack())
def __pollThread_inner(self):
"""super simple and super stupid per-module polling thread"""
i = 0
fastpoll = True # first update should be quick
while True:
i = 1
fastpoll = self.poll(i)
i += 1
try:
time.sleep(self.pollinterval * (0.1 if fastpoll else 1))
except TypeError:
time.sleep(min(self.pollinterval)
if fastpoll else max(self.pollinterval))
fastpoll = self.poll(i)
def poll(self, nr):
# poll status first
fastpoll = False
if 'status' in self.parameters:
stat = self.read_status(0)
# self.log.info('polling read_status -> %r' % (stat,))
fastpoll = stat[0] == status.BUSY
# if fastpoll:
# self.log.info('fastpoll!')
def poll(self, nr=0):
# Just poll all parameters regularly where polling is enabled
for pname, pobj in self.parameters.items():
if not pobj.poll:
continue
if pname == 'status':
# status was already polled above
continue
if ((int(pobj.poll) < 0) and fastpoll) or (
nr % abs(int(pobj.poll))) == 0:
# poll always if pobj.poll is negative and fastpoll (i.e. Module is busy)
# otherwise poll every 'pobj.poll' iteration
if nr % abs(int(pobj.poll)) == 0:
# poll every 'pobj.poll' iteration
rfunc = getattr(self, 'read_' + pname, None)
if rfunc:
try:
# self.log.info('polling read_%s -> %r' % (pname, rfunc()))
rfunc()
except Exception: # really all!
pass
return fastpoll
class Writable(Readable):
@ -527,6 +530,29 @@ class Drivable(Writable):
Also status gets extended with a BUSY state indicating a running action.
"""
# improved polling: may poll faster if module is BUSY
def poll(self, nr=0):
# poll status first
stat = self.read_status(0)
fastpoll = stat[0] == status.BUSY
for pname, pobj in self.parameters.items():
if not pobj.poll:
continue
if pname == 'status':
# status was already polled above
continue
if ((int(pobj.poll) < 0) and fastpoll) or (
nr % abs(int(pobj.poll))) == 0:
# poll always if pobj.poll is negative and fastpoll (i.e. Module is busy)
# otherwise poll every 'pobj.poll' iteration
rfunc = getattr(self, 'read_' + pname, None)
if rfunc:
try:
rfunc()
except Exception: # really all!
pass
return fastpoll
def do_stop(self):
"""default implementation of the stop command