1 |
Use time.monotonic() which is available in Python 3.3 and later, |
2 |
and otherwise emulate it by using an offset to counteract any |
3 |
backward movements. |
4 |
|
5 |
Bug: https://bugs.gentoo.org/591760 |
6 |
--- |
7 |
pym/portage/util/_eventloop/EventLoop.py | 19 ++++++++++++++----- |
8 |
pym/portage/util/monotonic.py | 32 ++++++++++++++++++++++++++++++++ |
9 |
2 files changed, 46 insertions(+), 5 deletions(-) |
10 |
create mode 100644 pym/portage/util/monotonic.py |
11 |
|
12 |
diff --git a/pym/portage/util/_eventloop/EventLoop.py b/pym/portage/util/_eventloop/EventLoop.py |
13 |
index 89ac2a3b3..f472a3dae 100644 |
14 |
--- a/pym/portage/util/_eventloop/EventLoop.py |
15 |
+++ b/pym/portage/util/_eventloop/EventLoop.py |
16 |
@@ -1,4 +1,4 @@ |
17 |
-# Copyright 1999-2016 Gentoo Foundation |
18 |
+# Copyright 1999-2018 Gentoo Foundation |
19 |
# Distributed under the terms of the GNU General Public License v2 |
20 |
|
21 |
from __future__ import division |
22 |
@@ -9,7 +9,6 @@ import os |
23 |
import select |
24 |
import signal |
25 |
import sys |
26 |
-import time |
27 |
|
28 |
try: |
29 |
import fcntl |
30 |
@@ -29,6 +28,7 @@ portage.proxy.lazyimport.lazyimport(globals(), |
31 |
|
32 |
from portage import OrderedDict |
33 |
from portage.util import writemsg_level |
34 |
+from portage.util.monotonic import monotonic |
35 |
from ..SlotObject import SlotObject |
36 |
from .PollConstants import PollConstants |
37 |
from .PollSelectAdapter import PollSelectAdapter |
38 |
@@ -515,7 +515,7 @@ class EventLoop(object): |
39 |
self._timeout_handlers[source_id] = \ |
40 |
self._timeout_handler_class( |
41 |
interval=interval, function=function, args=args, |
42 |
- source_id=source_id, timestamp=time.time()) |
43 |
+ source_id=source_id, timestamp=self.time()) |
44 |
if self._timeout_interval is None or \ |
45 |
self._timeout_interval > interval: |
46 |
self._timeout_interval = interval |
47 |
@@ -538,7 +538,7 @@ class EventLoop(object): |
48 |
return bool(calls) |
49 |
|
50 |
ready_timeouts = [] |
51 |
- current_time = time.time() |
52 |
+ current_time = self.time() |
53 |
for x in self._timeout_handlers.values(): |
54 |
elapsed_seconds = current_time - x.timestamp |
55 |
# elapsed_seconds < 0 means the system clock has been adjusted |
56 |
@@ -558,7 +558,7 @@ class EventLoop(object): |
57 |
calls += 1 |
58 |
x.calling = True |
59 |
try: |
60 |
- x.timestamp = time.time() |
61 |
+ x.timestamp = self.time() |
62 |
if not x.function(*x.args): |
63 |
self.source_remove(x.source_id) |
64 |
finally: |
65 |
@@ -684,6 +684,15 @@ class EventLoop(object): |
66 |
# The call_soon method inherits thread safety from the idle_add method. |
67 |
call_soon_threadsafe = call_soon |
68 |
|
69 |
+ def time(self): |
70 |
+ """Return the time according to the event loop's clock. |
71 |
+ |
72 |
+ This is a float expressed in seconds since an epoch, but the |
73 |
+ epoch, precision, accuracy and drift are unspecified and may |
74 |
+ differ per event loop. |
75 |
+ """ |
76 |
+ return monotonic() |
77 |
+ |
78 |
def call_later(self, delay, callback, *args): |
79 |
""" |
80 |
Arrange for the callback to be called after the given delay seconds |
81 |
diff --git a/pym/portage/util/monotonic.py b/pym/portage/util/monotonic.py |
82 |
new file mode 100644 |
83 |
index 000000000..da1cce1c5 |
84 |
--- /dev/null |
85 |
+++ b/pym/portage/util/monotonic.py |
86 |
@@ -0,0 +1,32 @@ |
87 |
+# Copyright 2018 Gentoo Foundation |
88 |
+# Distributed under the terms of the GNU General Public License v2 |
89 |
+ |
90 |
+__all__ = ['monotonic'] |
91 |
+ |
92 |
+import time |
93 |
+try: |
94 |
+ import threading |
95 |
+except ImportError: |
96 |
+ import dummy_threading as threading |
97 |
+ |
98 |
+monotonic = getattr(time, 'monotonic', None) |
99 |
+ |
100 |
+if monotonic is None: |
101 |
+ def monotonic(): |
102 |
+ """ |
103 |
+ Emulate time.monotonic() which is available in Python 3.3 and later. |
104 |
+ |
105 |
+ @return: A float expressed in seconds since an epoch. |
106 |
+ """ |
107 |
+ with monotonic._lock: |
108 |
+ current = time.time() |
109 |
+ delta = current - monotonic._previous |
110 |
+ if delta < 0: |
111 |
+ monotonic._offset -= delta |
112 |
+ monotonic._previous = current + monotonic._offset |
113 |
+ return monotonic._previous |
114 |
+ |
115 |
+ # offset is used to counteract any backward movements |
116 |
+ monotonic._offset = 0 |
117 |
+ monotonic._previous = time.time() |
118 |
+ monotonic._lock = threading.Lock() |
119 |
-- |
120 |
2.13.6 |