Search code examples
matlabtimercountdowntimer

Matlab: Detect if spawning function is running (from within periodic timer function)


I want to create a function in MATLAB (2020) that displays a countdown in the console. Using e.g., periodic timers, this can be easily achieved (see below), however I cannot delete the timer when the user presses CTRL+C during the pause(3.1) (and the continued execution of update_countdown would lead to confusing results, deleting characters in the console instead of just displaying the update time)

Since timers seem to run asynchronously, my idea is to detect whether the timer-spawning function main() is still running or has been terminated - however I can't seem to find a way to detect this from within the periodic timer function update_countdown.

Based on my knowledge about figures that have

  • a handle that can be detected as deleted and
  • a CloseRequestFcn() - a function that can be specified to run after a figure has been closed,

I suspect something like this ought to exist for functions.

(How) can I detect whether main() is currently running within my MATLAB processs (from within the periodic timer function update_countdown())?


%save as script and run
main

function main()
  timeout = 3;
  t1 = timer('ExecutionMode', 'singleShot', 'StartDelay', timeout, 'TimerFcn', @finish);
  t2 = timer('ExecutionMode', 'fixedRate','Period', 1, 'TimerFcn', {@update_countdown,datetime,timeout}); 
  %^datetime is a built-in function that passes the current time
  fprintf('countdown: %1i',timeout)
  start(t2); start(t1); %start timers
  pause(3.1); %<= arbitrary function 
  stop([t1 t2]); %stop timers
  delete([t1 t2]); %delete timers
  disp('Main: do more stuff!')
end


function update_countdown(src,ev,starttime,timeout) 
  %delete last displayed time, add new time (remaining)
  t=round(seconds(datetime-starttime)); % time running: current time - start time
  t=timeout - t;
  fprintf('\b%i',t); %delete last character and replace it with currently remaining time
end

function finish(src,ev)
  disp(' done!');
end

Solution

  • You can use the function onCleanup for this. It registers a function to call when the function exits (whether normally or through Ctrl-C). See also this documentation page.

    
    function main()
      timeout = 3;
      t1 = timer('ExecutionMode', 'singleShot', 'StartDelay', timeout, 'TimerFcn', @finish);
      t2 = timer('ExecutionMode', 'fixedRate','Period', 1, 'TimerFcn', {@update_countdown,datetime,timeout}); 
      %^datetime is a built-in function that passes the current time
    
      obj = onCleanup(@() delete([t1 t2])); %delete timers when function terminates
    
      fprintf('countdown: %1i',timeout)
      start(t2); start(t1); %start timers
      pause(3.1); %<= arbitrary function 
      stop([t1 t2]); %stop timers
      disp('Main: do more stuff!')
    end