Mercurial > hg > ishara
diff general/algo/iterate_timed.m @ 6:0ce3c2070089
Removed duplicate code and fixed doc in timed_action.
author | samer |
---|---|
date | Mon, 14 Jan 2013 14:33:37 +0000 |
parents | general/algo/iterate_timed2.m@e44f49929e56 |
children | beb8a3f4a345 |
line wrap: on
line diff
--- a/general/algo/iterate_timed.m Sat Jan 12 22:32:08 2013 +0000 +++ b/general/algo/iterate_timed.m Mon Jan 14 14:33:37 2013 +0000 @@ -1,126 +1,54 @@ -function api=iterate_timed(varargin) +function Sched=iterate_timed(nextfn,X0,T,varargin) % iterate_timed - Iterate function under control of timer % % iterate_timed :: % (A=>A) ~'state transformer action', % A ~'initial state', -% real ~'timer between updates in seconds', -% options iterate_timed_options ~'options (see below)' -% -> sched(A) ~'scheduler API'. -% -% iterate_timed :: -% cell { -% (A=>A) ~'state transformer action', -% A ~'initial state' -% } ~'iterated system as a cell array', -% real ~'timer between updates in seconds', -% options iterate_timed_options ~'options (see below)' -% -> sched(A) ~'scheduler API'. -% -% iterate_timed_options = { +% real ~'timer between updates in seconds' +% options { % drawnow :: {0,1} /0 ~'call drawnow after each iteration'; % busy_mode :: {'queue','drop'} /'queue' ~'See TIMER'; % exec_mode :: {'fixedRate','fixedDelay','fixedSpacing'} /'fixedRate' ~'See TIMER'; % its :: natural / inf ~'iteration limit'; -% onstart :: A->void / @nop ~'do this when timer starts'; -% onstop :: A->void / @nop ~'do this when timer stops'; -% onfinish :: A->void / @nop ~'do this when iterator terminates'; -% pre :: A->void / [] ~'something to do before each iteration'; -% post :: A->void / [] ~'something to do after each iteration'; -% drawnow :: bool / 0 ~'whether to update graphics every it'; +% onstart :: (A=>void)/ @nop ~'do this when timer starts'; +% onstop :: (A=>void)/ @nop ~'do this when timer stops'; +% onfinish :: (A=>void)/ @nop ~'do this when iterator terminates'; +% pre :: (A=>void)/ @nop ~'do before each iteration'; +% post :: (A=>void)/ @nop ~'do after each iteration'; % defer :: bool / 0 ~'if true then don't start the timer'; -% props :: {[[_]]} / {} ~'extra name/value pairs for timer' -% } +% -> timer, (A=>void) ~'function to seek to given state'. % -% sched(A) ::= struct { -% dispose :: void => void; -% isrunning :: void => bool; -% startat :: real => void; -% start :: void => void; -% stop :: void => void; -% rewind :: void => void; -% getstate :: void => A; -% setstate :: A => void -% }. -% % NB: Unlike ITERATE, this does NOT respect the id, save, and recover properties. % Neither does it respect the OPTPAUSE property 'pause'. - warning('off','MATLAB:TIMER:STARTDELAYPRECISION'); - warning('off','MATLAB:TIMER:RATEPRECISION'); - - if iscell(varargin{1}) - [nextfn,X0]=varargin{1}{:}; - T=varargin{2}; - options=varargin(3:end); - else - nextfn=varargin{1}; - X0=varargin{2}; - T=varargin{3}; - options=varargin(4:end); - end - opts=prefs('its',inf,'drawnow',0, 'quiet', 0, 'defer', 0, ... 'busy_mode','queue','exec_mode','fixedRate', ... - 'onfinish',@nop,'onstart',@nop,'onstop',@nop,options{:}); + 'onfinish',@nop,'onstart',@nop,'onstop',@nop,varargin{:}); + + it={nextfn,X0}; + if isfield(opts,'pre') || isfield(opts,'post') + it=bracket_it(it, getparam(opts,'pre',@nop), getparam(opts,'post',@nop)); + end + if opts.drawnow, it=drawnow_it(it); end + stfn=it{1}; - X=X0; %% !!! NB: this is a mutable shared local variable used by timercb + Sched=rsched(@action,it{2},T,nows,opts,'defer',1,... + 'onstart',@onstart,'onstop',@onstop,'onfinish',@onfinish); + if ~opts.defer, Sched.start(); end - if ~isfield(opts,'pre') && ~isfield(opts,'post') && ~opts.drawnow - stfn=nextfn; % streamlined version with no checks - else % version with calls to pre,post, and drawnow - prefn=getparam(opts,'pre',@nop); - postfn=getparam(opts,'post',@nop); - stfn=@bracket; - end - - tm=timer('ExecutionMode',opts.exec_mode,'BusyMode',opts.busy_mode, ... - 'TimerFcn',@timercb,'StartFcn',@startfn,'StopFcn',@stopfn, ... - 'TasksToExecute',opts.its,'Period',T); - - api=struct( ... - 'dispose', @()delete(tm), ... - 'isrunning',@()isrunning(tm), ... - 'startat', @(t)startat(tm,t/86400), ... - 'start', @()start(tm), ... - 'stop', @()stop(tm), ... - 'rewind', @()setstate(X0), ... - 'getstate', @getstate, ... - 'setstate', @setstate ... - ); - - if ~opts.defer, start(tm); end - - function setstate(x), X=x; end - function x=getstate, x=X; end - - function X=bracket(X), - prefn(X); X=nextfn(X); postfn(X); - if opts.drawnow, drawnow; end - end - - function startfn(tm,a) - if ~opts.quiet, status(tm,'starting',X,a.Data.time); end - opts.onstart(X); - end - - function stopfn(tm,a) - if ~opts.quiet, status(tm,'stopping',X,a.Data.time); end - opts.onstop(X); - if isempty(X), - if ~opts.quiet, status(tm,'finished',X,a.Data.time); end - opts.onfinish(X); + function [err,s]=action(t_sched,dt,s), err=nows-t_sched; s=stfn(s); end + function onstart(X,t_sched,t_actual), status('starting',X,t_actual); opts.onstart(X); end + function onstop(X,t_actual), status('stopping',X,t_actual); opts.onstop(X); end + function onfinish(t_actual), status('finishing',[],t_actual); opts.onfinish(); end + function status(msg,x,t), + if ~opts.quiet + fprintf('| %s at %s with %s\n',msg,mat2str(t),tostring(x)); end end - - % well, we have mutable variables captured by closure so we may - % as well use them... - function timercb(tm,ev) - if isempty(X), stop(tm); else, X=stfn(X); end - end end -function status(tm,msg,x,t), - fprintf('| %s %s at %s with %s\n',get(tm,'name'),msg,mat2str(t),tostring(x)); +function it=drawnow_it(it), + f=it{1}; it{1}=@fdraw; + function x=fdraw(x), x=f(x); drawnow; end end