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
|
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
import itertools
from threading import Timer, Lock
# Credit to https://stackoverflow.com/questions/3393612/run-certain-code-every-n-seconds
class RepeatedTimer(object):
def __init__(self, interval, function, *args, start_now: bool = True, **kwargs):
self._timer = None
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.is_running = False
if start_now:
self.start()
def _run(self):
self.is_running = False
self.start()
self.function(*self.args, **self.kwargs)
def start(self):
if not self.is_running:
# NOTE: If there is a concern about perf impact of this Timer, we'd need to convert to multiprocess and use IPC.
self._timer = Timer(self.interval, self._run)
self._timer.start()
self.is_running = True
def stop(self):
self._timer.cancel()
self.is_running = False
# Credit to https://julien.danjou.info/atomic-lock-free-counters-in-python/
class AtomicCounter(object):
def __init__(self):
self._number_of_read = 0
self._counter = itertools.count()
self._read_lock = Lock()
def increment(self):
next(self._counter)
def reset(self):
with self._read_lock:
self._number_of_read = 0
self._counter = itertools.count()
def value(self):
with self._read_lock:
value = next(self._counter) - self._number_of_read
self._number_of_read += 1
return value
|