Just in case someone is interested.
I came up with this solution since my previous
posting.
Maybe you've got some other ideas or critcism.
I'll listen ;-)
Ciao,
Dominic
P.S. Python is really powerful!
Use-Case:
def driveTask(handl er):
print " enter drive"
yield "current speed"
while 1:
try:
handler.registe r(driveTask, (NoPower, WallHit))
while 1:
print " adjust engine"
yield "current speed"
print " steer"
except WallHit:
print "hit the wall :-("
except NoPower:
print "need some fresh batteries :-)"
=============== =============== =============== =============== ========
Full-Source code:
from types import GeneratorType
class TaskHandler(obj ect):
def __init__(self):
self.tasks = []
def addTask(self, task):
self.tasks.appe nd(task)
def removeTask(self , task):
del self.tasks[task]
def loop(self):
for t in self.tasks:
# generator task
if type(t) == GeneratorType:
if not t.next():
# generator is done, remove it
self.tasks.remo ve(t)
else: # normal method/function
t()
from sys import settrace
class SignalingTaskHa ndler(TaskHandl er):
def __init__(self):
super(Signaling TaskHandler, self).__init__( )
self.function2s ignal = {}
self.activeSign als = ()
self.newSignals = []
self.loopTask = self.__loop()
def register(self, aFunction, signals):
self.function2s ignal[id(aFunction.fu nc_code)] = signals
def signal(self, aSignal):
if not aSignal in self.newSignals :
self.newSignals .append(aSignal )
def loop(self):
self.loopTask.n ext()
def __loop(self):
while 1:
settrace(self._ _intercept)
tmp = len(self.newSig nals)
try:
super(Signaling TaskHandler, self).loop()
finally:
settrace(None)
# if we've reached "steady state", we make a step
# I think Esterel-language has similar signaling semantics
if tmp == len(self.newSig nals):
self.__step()
yield True
def __step(self):
# switch to new signal set, discard old ones
self.activeSign als = tuple(self.newS ignals)
self.newSignals = []
def __intercept(sel f, frame, event, arg):
def _i(frame, event, arg):
# we could return _i to trace inside function
# and not only calls to it
if self.activeSign als:
signals = self.function2s ignal[key]
# check if there is one signal to raise
for s in self.activeSign als:
if s in signals:
raise s
# every function gets it's own tracer, otherwise
# exceptions cannot be catched :-( Why?
key = id(frame.f_code )
if key in self.function2s ignal:
return _i
return None
# A Use Case :
class WallHit(Excepti on):
pass
class NoPower(Excepti on):
pass
def driveTask(handl er):
print " enter drive"
yield "current speed"
while 1:
try:
handler.registe r(driveTask, (NoPower, WallHit))
while 1:
print " adjust engine"
yield "current speed"
print " steer"
except WallHit:
print "hit the wall :-("
except NoPower:
print "need some fresh batteries :-)"
counter = 0
def miscTask():
global counter
if counter == 4:
handler.signal( WallHit)
if counter == 5:
handler.signal( NoPower)
counter += 1
# "special" tasks with signaling
handler = SignalingTaskHa ndler()
tmp = driveTask(handl er)
handler.addTask (tmp)
# main loop
mainTaskHandler = TaskHandler()
# well, there could be a lot more
mainTaskHandler .addTask(miscTa sk)
mainTaskHandler .addTask(handle r.loop)
for _ in range(10):
mainTaskHandler .loop()
# enter drive
# adjust engine
# steer
# adjust engine
# steer
# adjust engine
# steer
# adjust engine
# hit the wall :-(
# adjust engine
# need some fresh batteries :-)
# adjust engine
# steer
# adjust engine
# steer
# adjust engine
# steer
# adjust engine
I came up with this solution since my previous
posting.
Maybe you've got some other ideas or critcism.
I'll listen ;-)
Ciao,
Dominic
P.S. Python is really powerful!
Use-Case:
def driveTask(handl er):
print " enter drive"
yield "current speed"
while 1:
try:
handler.registe r(driveTask, (NoPower, WallHit))
while 1:
print " adjust engine"
yield "current speed"
print " steer"
except WallHit:
print "hit the wall :-("
except NoPower:
print "need some fresh batteries :-)"
=============== =============== =============== =============== ========
Full-Source code:
from types import GeneratorType
class TaskHandler(obj ect):
def __init__(self):
self.tasks = []
def addTask(self, task):
self.tasks.appe nd(task)
def removeTask(self , task):
del self.tasks[task]
def loop(self):
for t in self.tasks:
# generator task
if type(t) == GeneratorType:
if not t.next():
# generator is done, remove it
self.tasks.remo ve(t)
else: # normal method/function
t()
from sys import settrace
class SignalingTaskHa ndler(TaskHandl er):
def __init__(self):
super(Signaling TaskHandler, self).__init__( )
self.function2s ignal = {}
self.activeSign als = ()
self.newSignals = []
self.loopTask = self.__loop()
def register(self, aFunction, signals):
self.function2s ignal[id(aFunction.fu nc_code)] = signals
def signal(self, aSignal):
if not aSignal in self.newSignals :
self.newSignals .append(aSignal )
def loop(self):
self.loopTask.n ext()
def __loop(self):
while 1:
settrace(self._ _intercept)
tmp = len(self.newSig nals)
try:
super(Signaling TaskHandler, self).loop()
finally:
settrace(None)
# if we've reached "steady state", we make a step
# I think Esterel-language has similar signaling semantics
if tmp == len(self.newSig nals):
self.__step()
yield True
def __step(self):
# switch to new signal set, discard old ones
self.activeSign als = tuple(self.newS ignals)
self.newSignals = []
def __intercept(sel f, frame, event, arg):
def _i(frame, event, arg):
# we could return _i to trace inside function
# and not only calls to it
if self.activeSign als:
signals = self.function2s ignal[key]
# check if there is one signal to raise
for s in self.activeSign als:
if s in signals:
raise s
# every function gets it's own tracer, otherwise
# exceptions cannot be catched :-( Why?
key = id(frame.f_code )
if key in self.function2s ignal:
return _i
return None
# A Use Case :
class WallHit(Excepti on):
pass
class NoPower(Excepti on):
pass
def driveTask(handl er):
print " enter drive"
yield "current speed"
while 1:
try:
handler.registe r(driveTask, (NoPower, WallHit))
while 1:
print " adjust engine"
yield "current speed"
print " steer"
except WallHit:
print "hit the wall :-("
except NoPower:
print "need some fresh batteries :-)"
counter = 0
def miscTask():
global counter
if counter == 4:
handler.signal( WallHit)
if counter == 5:
handler.signal( NoPower)
counter += 1
# "special" tasks with signaling
handler = SignalingTaskHa ndler()
tmp = driveTask(handl er)
handler.addTask (tmp)
# main loop
mainTaskHandler = TaskHandler()
# well, there could be a lot more
mainTaskHandler .addTask(miscTa sk)
mainTaskHandler .addTask(handle r.loop)
for _ in range(10):
mainTaskHandler .loop()
# enter drive
# adjust engine
# steer
# adjust engine
# steer
# adjust engine
# steer
# adjust engine
# hit the wall :-(
# adjust engine
# need some fresh batteries :-)
# adjust engine
# steer
# adjust engine
# steer
# adjust engine
# steer
# adjust engine
Comment