% uiterate - Run a processing unit for some number of iterations
%
% uiterate :: 
%    unit({}, _, _) ~'live processing unit',
%    T:natural      ~'number of iterations to run (can be inf)',
%    options {
%       draw  :: boolean/false ~'whether or not to call drawnow after each iteration';
%       quiet :: boolean/false ~'whether or not to suppress progress messages';
%       chunk :: natural/1     ~'print progress every chunk interations'
%    } 
% -> action ().
%
% This function accepts the live processing unit associated
% with an arrow (as created by with_arrow). The arrow must
% have zero inputs. Outputs are ignored. If inf iterations are
% requested, the system is run until an EOF exception is caught.

function uiterate(u,its,varargin)
	uiter1(u,its,u.process,'label','uiterate',varargin{:});
end

function itsdone=uiter1(u,its,itfn,varargin)
	opts=options('draw',1,'quiet',0,'chunk',1,varargin{:});
	quiet=opts.quiet; draw=opts.draw;
	chunk=opts.chunk;
	u.starting();
	try
		i=1;
		while i<=its, 
			if ~quiet && mod(i,chunk)==0, fprintf(' %s: %d   \r',opts.label,i); end
			itfn();
			if draw, drawnow; end
			i=i+1;
		end
	catch ex
		if ~iseof(ex)
			if ~quiet, fprintf('exception at %d iterations.\n',i); end
			u.stopping();
			rethrow(ex); 
		end
	end
	itsdone=i-1;
	if ~quiet, fprintf('done %d iterations.\n',itsdone); end
	u.stopping();
end
