Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH] EventLoop: implement time method for asyncio compat (bug 591760)
Date: Fri, 16 Mar 2018 09:01:54
Message-Id: 20180316085923.6361-1-zmedico@gentoo.org
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