comparison 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
comparison
equal deleted inserted replaced
5:8972a4071294 6:0ce3c2070089
1 function api=iterate_timed(varargin) 1 function Sched=iterate_timed(nextfn,X0,T,varargin)
2 % iterate_timed - Iterate function under control of timer 2 % iterate_timed - Iterate function under control of timer
3 % 3 %
4 % iterate_timed :: 4 % iterate_timed ::
5 % (A=>A) ~'state transformer action', 5 % (A=>A) ~'state transformer action',
6 % A ~'initial state', 6 % A ~'initial state',
7 % real ~'timer between updates in seconds', 7 % real ~'timer between updates in seconds'
8 % options iterate_timed_options ~'options (see below)' 8 % options {
9 % -> sched(A) ~'scheduler API'.
10 %
11 % iterate_timed ::
12 % cell {
13 % (A=>A) ~'state transformer action',
14 % A ~'initial state'
15 % } ~'iterated system as a cell array',
16 % real ~'timer between updates in seconds',
17 % options iterate_timed_options ~'options (see below)'
18 % -> sched(A) ~'scheduler API'.
19 %
20 % iterate_timed_options = {
21 % drawnow :: {0,1} /0 ~'call drawnow after each iteration'; 9 % drawnow :: {0,1} /0 ~'call drawnow after each iteration';
22 % busy_mode :: {'queue','drop'} /'queue' ~'See TIMER'; 10 % busy_mode :: {'queue','drop'} /'queue' ~'See TIMER';
23 % exec_mode :: {'fixedRate','fixedDelay','fixedSpacing'} /'fixedRate' ~'See TIMER'; 11 % exec_mode :: {'fixedRate','fixedDelay','fixedSpacing'} /'fixedRate' ~'See TIMER';
24 % its :: natural / inf ~'iteration limit'; 12 % its :: natural / inf ~'iteration limit';
25 % onstart :: A->void / @nop ~'do this when timer starts'; 13 % onstart :: (A=>void)/ @nop ~'do this when timer starts';
26 % onstop :: A->void / @nop ~'do this when timer stops'; 14 % onstop :: (A=>void)/ @nop ~'do this when timer stops';
27 % onfinish :: A->void / @nop ~'do this when iterator terminates'; 15 % onfinish :: (A=>void)/ @nop ~'do this when iterator terminates';
28 % pre :: A->void / [] ~'something to do before each iteration'; 16 % pre :: (A=>void)/ @nop ~'do before each iteration';
29 % post :: A->void / [] ~'something to do after each iteration'; 17 % post :: (A=>void)/ @nop ~'do after each iteration';
30 % drawnow :: bool / 0 ~'whether to update graphics every it';
31 % defer :: bool / 0 ~'if true then don't start the timer'; 18 % defer :: bool / 0 ~'if true then don't start the timer';
32 % props :: {[[_]]} / {} ~'extra name/value pairs for timer' 19 % -> timer, (A=>void) ~'function to seek to given state'.
33 % }
34 % 20 %
35 % sched(A) ::= struct {
36 % dispose :: void => void;
37 % isrunning :: void => bool;
38 % startat :: real => void;
39 % start :: void => void;
40 % stop :: void => void;
41 % rewind :: void => void;
42 % getstate :: void => A;
43 % setstate :: A => void
44 % }.
45 %
46 % NB: Unlike ITERATE, this does NOT respect the id, save, and recover properties. 21 % NB: Unlike ITERATE, this does NOT respect the id, save, and recover properties.
47 % Neither does it respect the OPTPAUSE property 'pause'. 22 % Neither does it respect the OPTPAUSE property 'pause'.
48 23
49 warning('off','MATLAB:TIMER:STARTDELAYPRECISION');
50 warning('off','MATLAB:TIMER:RATEPRECISION');
51
52 if iscell(varargin{1})
53 [nextfn,X0]=varargin{1}{:};
54 T=varargin{2};
55 options=varargin(3:end);
56 else
57 nextfn=varargin{1};
58 X0=varargin{2};
59 T=varargin{3};
60 options=varargin(4:end);
61 end
62
63 opts=prefs('its',inf,'drawnow',0, 'quiet', 0, 'defer', 0, ... 24 opts=prefs('its',inf,'drawnow',0, 'quiet', 0, 'defer', 0, ...
64 'busy_mode','queue','exec_mode','fixedRate', ... 25 'busy_mode','queue','exec_mode','fixedRate', ...
65 'onfinish',@nop,'onstart',@nop,'onstop',@nop,options{:}); 26 'onfinish',@nop,'onstart',@nop,'onstop',@nop,varargin{:});
27
28 it={nextfn,X0};
29 if isfield(opts,'pre') || isfield(opts,'post')
30 it=bracket_it(it, getparam(opts,'pre',@nop), getparam(opts,'post',@nop));
31 end
32 if opts.drawnow, it=drawnow_it(it); end
33 stfn=it{1};
66 34
67 X=X0; %% !!! NB: this is a mutable shared local variable used by timercb 35 Sched=rsched(@action,it{2},T,nows,opts,'defer',1,...
36 'onstart',@onstart,'onstop',@onstop,'onfinish',@onfinish);
37 if ~opts.defer, Sched.start(); end
68 38
69 if ~isfield(opts,'pre') && ~isfield(opts,'post') && ~opts.drawnow 39 function [err,s]=action(t_sched,dt,s), err=nows-t_sched; s=stfn(s); end
70 stfn=nextfn; % streamlined version with no checks 40 function onstart(X,t_sched,t_actual), status('starting',X,t_actual); opts.onstart(X); end
71 else % version with calls to pre,post, and drawnow 41 function onstop(X,t_actual), status('stopping',X,t_actual); opts.onstop(X); end
72 prefn=getparam(opts,'pre',@nop); 42 function onfinish(t_actual), status('finishing',[],t_actual); opts.onfinish(); end
73 postfn=getparam(opts,'post',@nop); 43 function status(msg,x,t),
74 stfn=@bracket; 44 if ~opts.quiet
75 end 45 fprintf('| %s at %s with %s\n',msg,mat2str(t),tostring(x));
76
77 tm=timer('ExecutionMode',opts.exec_mode,'BusyMode',opts.busy_mode, ...
78 'TimerFcn',@timercb,'StartFcn',@startfn,'StopFcn',@stopfn, ...
79 'TasksToExecute',opts.its,'Period',T);
80
81 api=struct( ...
82 'dispose', @()delete(tm), ...
83 'isrunning',@()isrunning(tm), ...
84 'startat', @(t)startat(tm,t/86400), ...
85 'start', @()start(tm), ...
86 'stop', @()stop(tm), ...
87 'rewind', @()setstate(X0), ...
88 'getstate', @getstate, ...
89 'setstate', @setstate ...
90 );
91
92 if ~opts.defer, start(tm); end
93
94 function setstate(x), X=x; end
95 function x=getstate, x=X; end
96
97 function X=bracket(X),
98 prefn(X); X=nextfn(X); postfn(X);
99 if opts.drawnow, drawnow; end
100 end
101
102 function startfn(tm,a)
103 if ~opts.quiet, status(tm,'starting',X,a.Data.time); end
104 opts.onstart(X);
105 end
106
107 function stopfn(tm,a)
108 if ~opts.quiet, status(tm,'stopping',X,a.Data.time); end
109 opts.onstop(X);
110 if isempty(X),
111 if ~opts.quiet, status(tm,'finished',X,a.Data.time); end
112 opts.onfinish(X);
113 end 46 end
114 end
115
116 % well, we have mutable variables captured by closure so we may
117 % as well use them...
118 function timercb(tm,ev)
119 if isempty(X), stop(tm); else, X=stfn(X); end
120 end 47 end
121 end 48 end
122 49
123 function status(tm,msg,x,t), 50 function it=drawnow_it(it),
124 fprintf('| %s %s at %s with %s\n',get(tm,'name'),msg,mat2str(t),tostring(x)); 51 f=it{1}; it{1}=@fdraw;
52 function x=fdraw(x), x=f(x); drawnow; end
125 end 53 end
126 54