commit:     a997f3e2d4318b8b9129d5cccd3c5f2c5677d11d
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Fri Mar 16 08:40:42 2018 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Fri Mar 16 17:17:53 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=a997f3e2

EventLoop: implement time method for asyncio compat (bug 591760)

Use time.monotonic() which is available in Python 3.3 and later,
and otherwise emulate it by using an offset to counteract any
backward movements.

Bug: https://bugs.gentoo.org/591760

 pym/portage/util/_eventloop/EventLoop.py | 19 +++++++++++++-----
 pym/portage/util/monotonic.py            | 34 ++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/pym/portage/util/_eventloop/EventLoop.py 
b/pym/portage/util/_eventloop/EventLoop.py
index 89ac2a3b3..f472a3dae 100644
--- a/pym/portage/util/_eventloop/EventLoop.py
+++ b/pym/portage/util/_eventloop/EventLoop.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2016 Gentoo Foundation
+# Copyright 1999-2018 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 from __future__ import division
@@ -9,7 +9,6 @@ import os
 import select
 import signal
 import sys
-import time
 
 try:
        import fcntl
@@ -29,6 +28,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
 
 from portage import OrderedDict
 from portage.util import writemsg_level
+from portage.util.monotonic import monotonic
 from ..SlotObject import SlotObject
 from .PollConstants import PollConstants
 from .PollSelectAdapter import PollSelectAdapter
@@ -515,7 +515,7 @@ class EventLoop(object):
                        self._timeout_handlers[source_id] = \
                                self._timeout_handler_class(
                                        interval=interval, function=function, 
args=args,
-                                       source_id=source_id, 
timestamp=time.time())
+                                       source_id=source_id, 
timestamp=self.time())
                        if self._timeout_interval is None or \
                                self._timeout_interval > interval:
                                self._timeout_interval = interval
@@ -538,7 +538,7 @@ class EventLoop(object):
                                return bool(calls)
 
                        ready_timeouts = []
-                       current_time = time.time()
+                       current_time = self.time()
                        for x in self._timeout_handlers.values():
                                elapsed_seconds = current_time - x.timestamp
                                # elapsed_seconds < 0 means the system clock 
has been adjusted
@@ -558,7 +558,7 @@ class EventLoop(object):
                                calls += 1
                                x.calling = True
                                try:
-                                       x.timestamp = time.time()
+                                       x.timestamp = self.time()
                                        if not x.function(*x.args):
                                                self.source_remove(x.source_id)
                                finally:
@@ -684,6 +684,15 @@ class EventLoop(object):
        # The call_soon method inherits thread safety from the idle_add method.
        call_soon_threadsafe = call_soon
 
+       def time(self):
+               """Return the time according to the event loop's clock.
+
+               This is a float expressed in seconds since an epoch, but the
+               epoch, precision, accuracy and drift are unspecified and may
+               differ per event loop.
+               """
+               return monotonic()
+
        def call_later(self, delay, callback, *args):
                """
                Arrange for the callback to be called after the given delay 
seconds

diff --git a/pym/portage/util/monotonic.py b/pym/portage/util/monotonic.py
new file mode 100644
index 000000000..e50564851
--- /dev/null
+++ b/pym/portage/util/monotonic.py
@@ -0,0 +1,34 @@
+# Copyright 2018 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+__all__ = ['monotonic']
+
+import time
+try:
+       import threading
+except ImportError:
+       import dummy_threading as threading
+
+monotonic = getattr(time, 'monotonic', None)
+
+if monotonic is None:
+       def monotonic():
+               """
+               Emulate time.monotonic() which is available in Python 3.3 and 
later.
+
+               @return: A float expressed in seconds since an epoch.
+               """
+               with monotonic._lock:
+                       current = time.time() + monotonic._offset
+                       delta = current - monotonic._previous
+                       if delta < 0:
+                               monotonic._offset -= delta
+                               current = monotonic._previous
+                       else:
+                               monotonic._previous = current
+                       return current
+
+       # offset is used to counteract any backward movements
+       monotonic._offset = 0
+       monotonic._previous = time.time()
+       monotonic._lock = threading.Lock()

Reply via email to