Mercurial > hg > ishara
view general/algo/iterate_timed.m @ 4:e44f49929e56
Adding reorganised general toolbox, now in several subdirectories.
author | samer |
---|---|
date | Sat, 12 Jan 2013 19:21:22 +0000 |
parents | |
children |
line wrap: on
line source
function api=iterate_timed(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 = { % 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'; % defer :: bool / 0 ~'if true then don't start the timer'; % props :: {[[_]]} / {} ~'extra name/value pairs for timer' % } % % 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{:}); X=X0; %% !!! NB: this is a mutable shared local variable used by timercb 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); 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)); end