-
Notifications
You must be signed in to change notification settings - Fork 58
/
greenify.pyx
91 lines (79 loc) · 2.46 KB
/
greenify.pyx
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
from gevent.hub import get_hub, getcurrent, Waiter
from gevent.timeout import Timeout
cdef extern from "libgreenify.h":
struct greenify_watcher:
int fd
int events
ctypedef int (*greenify_wait_callback_func_t) (greenify_watcher* watchers, int nwatchers, int timeout)
cdef void greenify_set_wait_callback(greenify_wait_callback_func_t callback)
cdef extern from "hook_greenify.h":
ctypedef enum greenified_function_t:
FN_CONNECT
FN_READ
FN_WRITE
FN_PREAD
FN_PWRITE
FN_READV
FN_WRITEV
FN_RECV
FN_SEND
FN_RECVMSG
FN_SENDMSG
FN_RECVFROM
FN_SENDTO
FN_SELECT
FN_POLL
void* greenify_patch_lib(const char* library_filename, greenified_function_t fn)
cdef int wait_gevent(greenify_watcher* watchers, int nwatchers, int timeout_in_ms) noexcept with gil:
cdef int fd, event
cdef float timeout_in_s
cdef int i
hub = get_hub()
watchers_list = []
for i in range(nwatchers):
fd = watchers[i].fd
event = watchers[i].events
watcher = hub.loop.io(fd, event)
watchers_list.append(watcher)
if timeout_in_ms != 0:
timeout_in_s = timeout_in_ms / 1000.0
t = Timeout.start_new(timeout_in_s)
try:
wait(watchers_list)
return 0
except Timeout:
return -1
finally:
t.cancel()
else:
wait(watchers_list)
return 0
def greenify():
greenify_set_wait_callback(wait_gevent)
def wait(watchers):
waiter = Waiter()
switch = waiter.switch
unique = object()
try:
count = len(watchers)
for watcher in watchers:
watcher.start(switch, unique)
result = waiter.get()
assert result is unique, 'Invalid switch into %s: %r' % (getcurrent(), result)
waiter.clear()
return result
finally:
for watcher in watchers:
watcher.stop()
cpdef patch_lib(library_path):
cdef char* path
if isinstance(library_path, unicode):
library_path = (<unicode>library_path).encode('utf8')
path = library_path
cdef bint result = False
for fn in (FN_CONNECT, FN_READ, FN_WRITE, FN_PREAD, FN_PWRITE, FN_READV,
FN_WRITEV, FN_RECV, FN_SEND, FN_RECVMSG, FN_SENDMSG,
FN_RECVFROM, FN_SENDTO, FN_SELECT, FN_POLL):
if NULL != greenify_patch_lib(path, fn):
result = True
return result