File: PsychWatchDog.m

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 86,796 kB
  • sloc: ansic: 176,245; cpp: 20,103; objc: 5,393; sh: 2,753; python: 1,397; php: 384; makefile: 193; java: 113
file content (125 lines) | stat: -rw-r--r-- 4,055 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
function PsychWatchDog(heartbeat)
% PsychWatchDog - Watchdog mechanism and error handler for Psychtoolbox.
%
% PsychWatchDog([heartbeat]);
%
% PsychWatchDog implements a watchdog timer under GNU/Octave. It is not
% supported under the Matlab runtime environment yet.
%
% After PsychWatchDog is enabled, it will become active as soon an Octave
% waits for user input, either via some keyboard input command within a
% script, or when the command prompt becomes active after a script has
% finished running, or been terminated by an error or a users CTRL+C
% interrupt.
%
% It will respond to the user pressing CTRL + . by closing all open
% onscreen windows. If a timeout was set, it will also automatically close
% all windows if the timeout is reached without a sign of life from the
% users script.
%
% Usage:
%
% 1. Call PsychWatchDog(heartbeat) once at the beginning of your script to
% enable the watchdog. A 'heartbeat' value of zero will only enable
% watching for CTRL + . key press. A 'heartbeat' value > 0 will set the
% timeout to 'heartbeat' seconds.
%
% 2. Periodically call PsychWatchDog; without arguments in your script to
% tell the watchdog that your code is still running properly. If Octave
% waits for input and more than 'heartbeat' seconds elapse since the last
% PsychWatchDog call, then the watchdog will trigger and close all windows.
%
% 3. At the end of your script, call PsychWatchDog(-1); to disable the
% watchdog again.
%
% You can call PsychWatchDog() with a vector of at least 2 keycodes as
% delivered by KbName to change the abort key combo from CTRL + . to some
% other arbitrary two key combination. E.g., ...
% PsychWatchDog([KbName('ESCAPE'), KbName('q')]);
% ... would change the abort key combo to ESCape key + q key.
%

% History:
% 1.6.2009   mk Written.

persistent panickeyCodes;
persistent panicdeadline;
persistent heartbeatinterval;

if isempty(panickeyCodes)
    KbName('UnifyKeyNames');    
    panickeyCodes = [ KbName('LeftControl'), KbName('.>') ];
    panicdeadline = inf;
    heartbeatinterval = -1;
    
    % Attach to callback:
    if IsOctave
        add_input_event_hook(mfilename, []);
    end
end

if nargin == 0
    % Heartbeat signal from usercode:
    % Update timeout from heartbeat:
    panicdeadline = GetSecs + heartbeatinterval;
    fprintf('PsychWatchDog: Heartbeat! [Timeout %f] Deadline at %f.\n', heartbeatinterval, panicdeadline);
    return;
end

% Called from usercode to setup/disable/modify settings or heartbeat?
if ~isempty(heartbeat)
    if ~isscalar(heartbeat)
        % heartbeat is a vector of panickeycodes:
        panickeyCodes = heartbeat;
        return;
    end
    
    % Set timeout heartbeat interval value:
    heartbeatinterval = heartbeat;
    panicdeadline     = GetSecs + heartbeatinterval;

    if heartbeat == -1
        % Disable and detach:
        if IsOctave
            remove_input_event_hook(mfilename);
        end
        
        panickeyCodes = [];
    end
    
    return;
end

% Called from runtime system periodically to perform watchdog-cycle:
% Any windows open? Otherwise we got nothing to do...
if (~isempty(Screen('Windows'))) && (heartbeatinterval > -1)
    % Yes. Need to watchdog'em:
    [isdown tnow keycodes] = KbCheck(-1);
    
    if (tnow > panicdeadline) && (heartbeatinterval > 0)
        % Timeout: Close screens.

        % Disable ourselves:
        heartbeatinterval = -1;

        warning('PsychWatchDog: Timeout for heartbeat signal reached. Auto-Closing windows.'); %#ok<WNTAG>
        sca;
        return;
    end
    
    if isdown
        if all(keycodes(panickeyCodes))
            % CTRL + C pressed: Close screens.

            % Disable ourselves:
            heartbeatinterval = -1;

            warning('PsychWatchDog: Abort key combo (e.g., CTRL + .) pressed by user. Auto-Closing windows.'); %#ok<WNTAG>
            sca;
            return;
        end
    end
    
    % Boring watchdog cycle - Everything fine.
    % fprintf('PsychWatchDog: [Timeout %f] All fine at %f.\n', heartbeatinterval, tnow);
end