|
timing tasks
>It would be nice to have
>an alternative to stepframe which doesn't call on an
>updatestage, but in the absence of that, can anyone think of a workround?
>
>The only possibility I can think of is to use a global fake actorlist and
>call all objects in it on every exitframe (or enterframe), but it's a bit
>messy.
>
The timeoutScript could be used for that.
Another possible source of regular events would be the idle event which
occurs quite often. In fact, much to often for most practical purposes, so
you will need some sort of filter which enables you to act only on every
nth idle event, or better: act on the first event after some dt duration of
time has passed.
Below are 2 parent scripts which together act as a timeout deluxe.
The first script represents the job to be done. You create it with a
property list specifying the task to be done and an ObjReference as
parameters.
-- parent script -----
-- Job - Objekt
--
-- Aufruf:
-- new (script "JobObj",[#task:"doAble" oder #sendAble, #caller:<ObjRef>, ¬
#Param: (optional),#msFrist:100,#Type:#single/#period/Integer],<ObjRef>)
-- i.e.
-- new (script "JobObj",[#task:#blink, #caller:new(script "blinkObj",1), ¬
#msFrist:200, #Param: #red,#Type:#period], gObjRef)
-- new (script "JobObj",[#task:"set the text of member 7 = the time", ¬
#caller:"", #msFrist:60000, #Type:#single], gObjRef)
-------------
property myLpParam
on new me, LpParam,CustomTimerObj
me.init (LpParam,CustomTimerObj)
return me
end
on init me,LpParam,CustomTimerObj
myLpParam=LpParam
me.subscribe(CustomTimerObj)
end
------------------------
on subscribe me,CustomTimerObj
if ilk(CustomTimerObj)<>#instance then return #error_missingObjRef
msFrist=myLpParam.getaprop(#msFrist)
dMoment=the milliseconds + msFrist
CustomTimerObj.addKick(dMoment,me)
end
on timeKick me,dObj
dType = myLpParam.getaprop(#type)
-- NewEntry
if dType <> #single then
if (IntegerP(dType) and dType>0) then myLpParam.setaProp (#Type,dType-1)
if dType <> 0 then me.subscribe(dObj)
end if
-- PayLoad
me.payLoad()
end
on payLoad me
dTask = myLpParam.getaProp(#task)
dCaller = myLpParam.getaProp(#caller)
dParam = myLpParam.getaProp(#param)
if stringP(dTask) then
do dTask
else
if symbolP(dTask) and objectP(dCaller) then
call (dTask,dCaller,dParam)
end if
end if
end
-- EoS
The second script queues the waiting jobs, checks if their time has come
and if so, triggers their execution. This is the one which is called with
every idle event. While I create a new instance of the jobObj for any new
task scheduled there is only 1 instance of this object which is stored
globally. Its reference is the second parameter when birthing a new jobObj.
-- parent script CustomTimer - Objekt
--
-- Aufruf:
--new script "CustomTimerObj"
-------------
property myLpKicks,myActive
on new me
me.init()
return me
end
on init me
myLpKicks=[:]
sort myLpKicks
myActive=TRUE
end
------------------------
on Kick me
if myActive then
if myLpKicks.Count > 0 then
dMsecs = myLpKicks.getPropAt(1)
if the milliseconds >= dMsecs then
dObj = myLpKicks[1]
myLpKicks.deleteAt(1)
if objectP(dObj) then dObj.timeKick()
end if
end if
end if
end
on AddKick me, dTicks,dObj
myLpKicks.addProp( dTicks,dObj )
return TRUE
end
on setActive me,dVal
if voidP(dVal) then dVal = TRUE
myActive = dVal
end
--------------------
on diag me
erg=[:]
addprop erg,#JobsWaiting,Count(myLpKicks)
return erg
end
-- EoS
The third element is to direct idle events to the CustomTimerObj like:
on idle
global gCustomTimerObj
if gCustomTimerObj.ilk = #instance then gCustomTimerObj.Kick()
pass
end
The object has a setActive method which allows to switch it off and on again.
There are two supported ways to define a task when subscribing a new Job:
you can make it as a call of a handler of some script instance or formulate
it as a doAble string
ie, if you had a parent script blinkObj with a handler 'on blink me,dColor'
you could make it blink red continuosly 5 times a second by:
new (script "JobObj",[#task:#blink, #caller:new(script "blinkObj",1), ¬
#msFrist:200, #Param: #red,#Type:#period], gObjRef)
Birthing a new jobObj returns a obj reference but you need not store it
somewhere, or rather, you shouldn't. The new job stores itself at the
global obj it gets passed at birth and survives the garbage collection
thanks to beeing referenced there. When its time has come the
customTimerObj deletes the refernce so the object representing the job
vanishes instantly after the task has been done.
caveat: I did some editing in the emailer, translated handlerNames etc so I
may have added errors to it.
Daniel Plaenitz
|