1# Copyright (C) 2016 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15'''Timer utility'''
16
17from __future__ import absolute_import
18
19import threading
20
21
22class Timer(object):
23    '''A Timer utility to execute a callback after a certain interval.'''
24
25    def __init__(self, interval, callback):
26        '''Initialise the Timer without starting it.
27
28        Args:
29            interval: int or float, interval in seconds to count, before
30                invoking the callback
31            callback: function, it handles the function to call once
32                the timeout expires.
33        '''
34
35        # validate input parameters
36        if not isinstance(interval, (int, float)):
37            raise TypeError('Argument "interval" is not a number: '
38                             '{0}'.format(type(interval)))
39        if not callable(callback):
40            raise TypeError('Argument "callback" is not a function: '
41                             '{0}'.format(type(callback)))
42
43        self._timer = None
44        self._callback = callback
45        self._interval = interval
46
47    def _is_running(self):
48        '''Checks whether the timer is executing.
49
50        Returns:
51            boolean, true if the timer is currently running, false otherwise
52        '''
53        return self._timer is not None
54
55    def start(self):
56        '''Starts the timer.
57
58        Returns:
59            self, the Timer instance
60
61        Throws:
62            RuntimeError: if the timer is already running
63        '''
64        if self._is_running():
65            raise RuntimeError('Timer already running')
66
67        self._timer = threading.Timer(self._interval, self._callback)
68        self._timer.start()
69        return self # so that we can perform Timer(...).start()
70
71    def stop(self):
72        '''Stops the timer if it's executing.
73
74        Returns:
75            self, the Timer instance
76        '''
77
78        if self._is_running():
79            self._timer.cancel()
80            self._timer = None
81        return self
82
83    def reset(self):
84        '''Restart the timer.
85
86        Returns:
87            self, the Timer instance
88        '''
89
90        self.stop()
91        self.start()
92        return self
93