Spaces:
Sleeping
Sleeping
import time | |
from abc import ABCMeta, abstractmethod | |
from typing import Union | |
from ..lock_helper import LockContext, LockContextType | |
class BaseTime(metaclass=ABCMeta): | |
""" | |
Overview: | |
Abstract time interface | |
Interfaces: | |
``time`` | |
""" | |
def time(self) -> Union[int, float]: | |
""" | |
Overview: | |
Get time information | |
Returns: | |
- time(:obj:`float, int`): time information | |
""" | |
raise NotImplementedError | |
class NaturalTime(BaseTime): | |
""" | |
Overview: | |
Natural time object | |
Interfaces: | |
``__init__``, ``time`` | |
Example: | |
>>> from ding.utils.autolog.time_ctl import NaturalTime | |
>>> time_ = NaturalTime() | |
""" | |
def __init__(self): | |
self.__last_time = None | |
def time(self) -> float: | |
""" | |
Overview: | |
Get current natural time (float format, unix timestamp) | |
Returns: | |
- time(:obj:`float`): unix timestamp | |
Example: | |
>>> from ding.utils.autolog.time_ctl import NaturalTime | |
>>> time_ = NaturalTime() | |
>>> time_.time() | |
1603896383.8811457 | |
""" | |
_current_time = time.time() | |
if self.__last_time is not None: | |
_current_time = max(_current_time, self.__last_time) | |
self.__last_time = _current_time | |
return _current_time | |
class TickTime(BaseTime): | |
""" | |
Overview: | |
Tick time object | |
Interfaces: | |
``__init__``, ``step``, ``time`` | |
Example: | |
>>> from ding.utils.autolog.time_ctl import TickTime | |
>>> time_ = TickTime() | |
""" | |
def __init__(self, init: int = 0): | |
""" | |
Overview: | |
Constructor of TickTime | |
Arguments: | |
- init (:obj:`int`): initial time, default is 0 | |
""" | |
self.__tick_time = init | |
def step(self, delta: int = 1) -> int: | |
""" | |
Overview | |
Step the time forward for this TickTime | |
Arguments: | |
- delta (:obj:`int`): steps to step forward, default is 1 | |
Returns: | |
- time (:obj:`int`): new time after stepping | |
Example: | |
>>> from ding.utils.autolog.time_ctl import TickTime | |
>>> time_ = TickTime(0) | |
>>> time_.step() | |
1 | |
>>> time_.step(2) | |
3 | |
""" | |
if not isinstance(delta, int): | |
raise TypeError("Delta should be positive int, but {actual} found.".format(actual=type(delta).__name__)) | |
elif delta < 1: | |
raise ValueError("Delta should be no less than 1, but {actual} found.".format(actual=repr(delta))) | |
else: | |
self.__tick_time += delta | |
return self.__tick_time | |
def time(self) -> int: | |
""" | |
Overview | |
Get current tick time | |
Returns: | |
int: current tick time | |
Example: | |
>>> from ding.utils.autolog.time_ctl import TickTime | |
>>> time_ = TickTime(0) | |
>>> time_.step() | |
>>> time_.time() | |
1 | |
""" | |
return self.__tick_time | |
class TimeProxy(BaseTime): | |
""" | |
Overview: | |
Proxy of time object, it can freeze time, sometimes useful when reproducing. | |
This object is thread-safe, and also freeze and unfreeze operation is strictly ordered. | |
Interfaces: | |
``__init__``, ``freeze``, ``unfreeze``, ``time``, ``current_time`` | |
Example: | |
>>> from ding.utils.autolog.time_ctl import TickTime, TimeProxy | |
>>> tick_time_ = TickTime() | |
>>> time_ = TimeProxy(tick_time_) | |
>>> tick_time_.step() | |
>>> print(tick_time_.time(), time_.time(), time_.current_time()) | |
1 1 1 | |
>>> time_.freeze() | |
>>> tick_time_.step() | |
>>> print(tick_time_.time(), time_.time(), time_.current_time()) | |
2 1 2 | |
>>> time_.unfreeze() | |
>>> print(tick_time_.time(), time_.time(), time_.current_time()) | |
2 2 2 | |
""" | |
def __init__(self, time_: BaseTime, frozen: bool = False, lock_type: LockContextType = LockContextType.THREAD_LOCK): | |
""" | |
Overview: | |
Constructor for Time proxy | |
Arguments: | |
- time_ (:obj:`BaseTime`): another time object it based on | |
- frozen (:obj:`bool`): this object will be frozen immediately if true, otherwise not, default is False | |
- lock_type (:obj:`LockContextType`): type of the lock, default is THREAD_LOCK | |
""" | |
self.__time = time_ | |
self.__current_time = self.__time.time() | |
self.__frozen = frozen | |
self.__lock = LockContext(lock_type) | |
self.__frozen_lock = LockContext(lock_type) | |
if self.__frozen: | |
self.__frozen_lock.acquire() | |
def is_frozen(self) -> bool: | |
""" | |
Overview: | |
Get if this time proxy object is frozen | |
Returns: | |
bool: true if it is frozen, otherwise false | |
""" | |
with self.__lock: | |
return self.__frozen | |
def freeze(self): | |
""" | |
Overview: | |
Freeze this time proxy | |
""" | |
with self.__lock: | |
self.__frozen_lock.acquire() | |
self.__frozen = True | |
self.__current_time = self.__time.time() | |
def unfreeze(self): | |
""" | |
Overview: | |
Unfreeze this time proxy | |
""" | |
with self.__lock: | |
self.__frozen = False | |
self.__frozen_lock.release() | |
def time(self) -> Union[int, float]: | |
""" | |
Overview: | |
Get time (may be frozen time) | |
Returns: | |
int or float: the time | |
""" | |
with self.__lock: | |
if self.__frozen: | |
return self.__current_time | |
else: | |
return self.__time.time() | |
def current_time(self) -> Union[int, float]: | |
""" | |
Overview: | |
Get current time (will not be frozen time) | |
Returns: | |
int or float: current time | |
""" | |
return self.__time.time() | |