Welcome to mirror list, hosted at ThFree Co, Russian Federation.

reactor.py « klippy - github.com/Klipper3d/klipper.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e07c64402903ce5a5ade305dd2274315b90cfbce (plain)
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File descriptor and timer event helper
#
# Copyright (C) 2016  Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.

import select, time, math

class ReactorTimer:
    def __init__(self, callback, waketime):
        self.callback = callback
        self.waketime = waketime

class ReactorFileHandler:
    def __init__(self, fd, callback):
        self.fd = fd
        self.callback = callback
    def fileno(self):
        return self.fd

class SelectReactor:
    NOW = 0.
    NEVER = 9999999999999999.
    def __init__(self):
        self._fds = []
        self._timers = []
        self._next_timer = self.NEVER
        self._process = True
    # Timers
    def _note_time(self, t):
        nexttime = t.waketime
        if nexttime < self._next_timer:
            self._next_timer = nexttime
    def update_timer(self, t, nexttime):
        t.waketime = nexttime
        self._note_time(t)
    def register_timer(self, callback, waketime = NEVER):
        handler = ReactorTimer(callback, waketime)
        timers = list(self._timers)
        timers.append(handler)
        self._timers = timers
        self._note_time(handler)
        return handler
    def unregister_timer(self, handler):
        timers = list(self._timers)
        timers.pop(timers.index(handler))
        self._timers = timers
    def _check_timers(self, eventtime):
        if eventtime < self._next_timer:
            return min(1., max(.001, self._next_timer - eventtime))
        self._next_timer = self.NEVER
        for t in self._timers:
            if eventtime >= t.waketime:
                t.waketime = t.callback(eventtime)
            self._note_time(t)
        if eventtime >= self._next_timer:
            return 0.
        return min(1., max(.001, self._next_timer - time.time()))
    # File descriptors
    def register_fd(self, fd, callback):
        handler = ReactorFileHandler(fd, callback)
        self._fds.append(handler)
        return handler
    def unregister_fd(self, handler):
        self._fds.pop(self._fds.index(handler))
    # Main loop
    def run(self):
        self._process = True
        eventtime = time.time()
        while self._process:
            timeout = self._check_timers(eventtime)
            res = select.select(self._fds, [], [], timeout)
            eventtime = time.time()
            for fd in res[0]:
                fd.callback(eventtime)
    def end(self):
        self._process = False

class PollReactor(SelectReactor):
    def __init__(self):
        SelectReactor.__init__(self)
        self._poll = select.poll()
        self._fds = {}
    # File descriptors
    def register_fd(self, fd, callback):
        handler = ReactorFileHandler(fd, callback)
        fds = self._fds.copy()
        fds[fd] = callback
        self._fds = fds
        self._poll.register(handler, select.POLLIN | select.POLLHUP)
        return handler
    def unregister_fd(self, handler):
        self._poll.unregister(handler)
        fds = self._fds.copy()
        del fds[handler.fd]
        self._fds = fds
    # Main loop
    def run(self):
        self._process = True
        eventtime = time.time()
        while self._process:
            timeout = int(math.ceil(self._check_timers(eventtime) * 1000.))
            res = self._poll.poll(timeout)
            eventtime = time.time()
            for fd, event in res:
                self._fds[fd](eventtime)

class EPollReactor(SelectReactor):
    def __init__(self):
        SelectReactor.__init__(self)
        self._epoll = select.epoll()
        self._fds = {}
    # File descriptors
    def register_fd(self, fd, callback):
        handler = ReactorFileHandler(fd, callback)
        fds = self._fds.copy()
        fds[fd] = callback
        self._fds = fds
        self._epoll.register(fd, select.EPOLLIN | select.EPOLLHUP)
        return handler
    def unregister_fd(self, handler):
        self._epoll.unregister(handler.fd)
        fds = self._fds.copy()
        del fds[handler.fd]
        self._fds = fds
    # Main loop
    def run(self):
        self._process = True
        eventtime = time.time()
        while self._process:
            timeout = self._check_timers(eventtime)
            res = self._epoll.poll(timeout)
            eventtime = time.time()
            for fd, event in res:
                self._fds[fd](eventtime)

# Use the poll based reactor if it is available
try:
    select.poll
    Reactor = PollReactor
except:
    Reactor = SelectReactor