polyphony 0.47.3 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +318 -295
- data/Gemfile.lock +1 -1
- data/LICENSE +1 -1
- data/TODO.md +40 -27
- data/examples/core/supervisor.rb +3 -3
- data/examples/core/worker-thread.rb +3 -4
- data/examples/io/tcp_proxy.rb +32 -0
- data/examples/io/unix_socket.rb +26 -0
- data/examples/performance/line_splitting.rb +34 -0
- data/examples/performance/loop.rb +32 -0
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +6 -0
- data/ext/polyphony/backend_common.h +2 -2
- data/ext/polyphony/backend_io_uring.c +42 -83
- data/ext/polyphony/backend_libev.c +32 -77
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/polyphony.c +0 -2
- data/ext/polyphony/polyphony.h +5 -4
- data/ext/polyphony/queue.c +2 -2
- data/ext/polyphony/thread.c +9 -28
- data/lib/polyphony.rb +1 -0
- data/lib/polyphony/adapters/postgres.rb +3 -3
- data/lib/polyphony/core/global_api.rb +14 -2
- data/lib/polyphony/core/thread_pool.rb +3 -1
- data/lib/polyphony/core/throttler.rb +1 -1
- data/lib/polyphony/core/timer.rb +72 -0
- data/lib/polyphony/extensions/fiber.rb +32 -8
- data/lib/polyphony/extensions/io.rb +8 -14
- data/lib/polyphony/extensions/openssl.rb +4 -4
- data/lib/polyphony/extensions/socket.rb +68 -16
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -1
- data/test/helper.rb +1 -0
- data/test/test_backend.rb +1 -1
- data/test/test_fiber.rb +64 -1
- data/test/test_global_api.rb +30 -0
- data/test/test_io.rb +26 -0
- data/test/test_socket.rb +32 -6
- data/test/test_supervise.rb +2 -1
- data/test/test_timer.rb +122 -0
- metadata +9 -4
- data/ext/polyphony/backend.h +0 -26
@@ -13,7 +13,6 @@
|
|
13
13
|
#include "../libev/ev.h"
|
14
14
|
#include "ruby/io.h"
|
15
15
|
|
16
|
-
VALUE cTCPSocket;
|
17
16
|
VALUE SYM_libev;
|
18
17
|
|
19
18
|
ID ID_ivar_is_nonblocking;
|
@@ -41,11 +40,14 @@ inline void io_set_nonblock(rb_io_t *fptr, VALUE io) {
|
|
41
40
|
}
|
42
41
|
|
43
42
|
typedef struct Backend_t {
|
43
|
+
// common fields
|
44
|
+
unsigned int currently_polling;
|
45
|
+
unsigned int pending_count;
|
46
|
+
unsigned int poll_no_wait_count;
|
47
|
+
|
48
|
+
// implementation-specific fields
|
44
49
|
struct ev_loop *ev_loop;
|
45
50
|
struct ev_async break_async;
|
46
|
-
int running;
|
47
|
-
int ref_count;
|
48
|
-
int run_no_wait_count;
|
49
51
|
} Backend_t;
|
50
52
|
|
51
53
|
static size_t Backend_size(const void *ptr) {
|
@@ -84,9 +86,9 @@ static VALUE Backend_initialize(VALUE self) {
|
|
84
86
|
ev_async_start(backend->ev_loop, &backend->break_async);
|
85
87
|
ev_unref(backend->ev_loop); // don't count the break_async watcher
|
86
88
|
|
87
|
-
backend->
|
88
|
-
backend->
|
89
|
-
backend->
|
89
|
+
backend->currently_polling = 0;
|
90
|
+
backend->pending_count = 0;
|
91
|
+
backend->poll_no_wait_count = 0;
|
90
92
|
|
91
93
|
return Qnil;
|
92
94
|
}
|
@@ -117,42 +119,11 @@ VALUE Backend_post_fork(VALUE self) {
|
|
117
119
|
return self;
|
118
120
|
}
|
119
121
|
|
120
|
-
|
122
|
+
unsigned int Backend_pending_count(VALUE self) {
|
121
123
|
Backend_t *backend;
|
122
124
|
GetBackend(self, backend);
|
123
125
|
|
124
|
-
backend->
|
125
|
-
return self;
|
126
|
-
}
|
127
|
-
|
128
|
-
VALUE Backend_unref(VALUE self) {
|
129
|
-
Backend_t *backend;
|
130
|
-
GetBackend(self, backend);
|
131
|
-
|
132
|
-
backend->ref_count--;
|
133
|
-
return self;
|
134
|
-
}
|
135
|
-
|
136
|
-
int Backend_ref_count(VALUE self) {
|
137
|
-
Backend_t *backend;
|
138
|
-
GetBackend(self, backend);
|
139
|
-
|
140
|
-
return backend->ref_count;
|
141
|
-
}
|
142
|
-
|
143
|
-
void Backend_reset_ref_count(VALUE self) {
|
144
|
-
Backend_t *backend;
|
145
|
-
GetBackend(self, backend);
|
146
|
-
|
147
|
-
backend->ref_count = 0;
|
148
|
-
}
|
149
|
-
|
150
|
-
VALUE Backend_pending_count(VALUE self) {
|
151
|
-
int count;
|
152
|
-
Backend_t *backend;
|
153
|
-
GetBackend(self, backend);
|
154
|
-
count = ev_pending_count(backend->ev_loop);
|
155
|
-
return INT2NUM(count);
|
126
|
+
return backend->pending_count;
|
156
127
|
}
|
157
128
|
|
158
129
|
VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue) {
|
@@ -161,19 +132,19 @@ VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue
|
|
161
132
|
GetBackend(self, backend);
|
162
133
|
|
163
134
|
if (is_nowait) {
|
164
|
-
backend->
|
165
|
-
if (backend->
|
135
|
+
backend->poll_no_wait_count++;
|
136
|
+
if (backend->poll_no_wait_count < 10) return self;
|
166
137
|
|
167
138
|
long runnable_count = Runqueue_len(runqueue);
|
168
|
-
if (backend->
|
139
|
+
if (backend->poll_no_wait_count < runnable_count) return self;
|
169
140
|
}
|
170
141
|
|
171
|
-
backend->
|
142
|
+
backend->poll_no_wait_count = 0;
|
172
143
|
|
173
144
|
COND_TRACE(2, SYM_fiber_event_poll_enter, current_fiber);
|
174
|
-
backend->
|
145
|
+
backend->currently_polling = 1;
|
175
146
|
ev_run(backend->ev_loop, is_nowait ? EVRUN_NOWAIT : EVRUN_ONCE);
|
176
|
-
backend->
|
147
|
+
backend->currently_polling = 0;
|
177
148
|
COND_TRACE(2, SYM_fiber_event_poll_leave, current_fiber);
|
178
149
|
|
179
150
|
return self;
|
@@ -183,7 +154,7 @@ VALUE Backend_wakeup(VALUE self) {
|
|
183
154
|
Backend_t *backend;
|
184
155
|
GetBackend(self, backend);
|
185
156
|
|
186
|
-
if (backend->
|
157
|
+
if (backend->currently_polling) {
|
187
158
|
// Since the loop will run until at least one event has occurred, we signal
|
188
159
|
// the selector's associated async watcher, which will cause the ev loop to
|
189
160
|
// return. In contrast to using `ev_break` to break out of the loop, which
|
@@ -494,7 +465,7 @@ VALUE Backend_write_m(int argc, VALUE *argv, VALUE self) {
|
|
494
465
|
Backend_writev(self, argv[0], argc - 1, argv + 1);
|
495
466
|
}
|
496
467
|
|
497
|
-
VALUE Backend_accept(VALUE self, VALUE
|
468
|
+
VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
498
469
|
Backend_t *backend;
|
499
470
|
struct libev_io watcher;
|
500
471
|
rb_io_t *fptr;
|
@@ -502,12 +473,12 @@ VALUE Backend_accept(VALUE self, VALUE sock) {
|
|
502
473
|
struct sockaddr addr;
|
503
474
|
socklen_t len = (socklen_t)sizeof addr;
|
504
475
|
VALUE switchpoint_result = Qnil;
|
505
|
-
VALUE underlying_sock = rb_ivar_get(
|
506
|
-
if (underlying_sock != Qnil)
|
476
|
+
VALUE underlying_sock = rb_ivar_get(server_socket, ID_ivar_io);
|
477
|
+
if (underlying_sock != Qnil) server_socket = underlying_sock;
|
507
478
|
|
508
479
|
GetBackend(self, backend);
|
509
|
-
GetOpenFile(
|
510
|
-
io_set_nonblock(fptr,
|
480
|
+
GetOpenFile(server_socket, fptr);
|
481
|
+
io_set_nonblock(fptr, server_socket);
|
511
482
|
watcher.fiber = Qnil;
|
512
483
|
while (1) {
|
513
484
|
fd = accept(fptr->fd, &addr, &len);
|
@@ -529,7 +500,7 @@ VALUE Backend_accept(VALUE self, VALUE sock) {
|
|
529
500
|
goto error;
|
530
501
|
}
|
531
502
|
|
532
|
-
socket = rb_obj_alloc(
|
503
|
+
socket = rb_obj_alloc(socket_class);
|
533
504
|
MakeOpenFile(socket, fp);
|
534
505
|
rb_update_max_fd(fd);
|
535
506
|
fp->fd = fd;
|
@@ -550,7 +521,7 @@ error:
|
|
550
521
|
return RAISE_EXCEPTION(switchpoint_result);
|
551
522
|
}
|
552
523
|
|
553
|
-
VALUE Backend_accept_loop(VALUE self, VALUE
|
524
|
+
VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
554
525
|
Backend_t *backend;
|
555
526
|
struct libev_io watcher;
|
556
527
|
rb_io_t *fptr;
|
@@ -559,12 +530,12 @@ VALUE Backend_accept_loop(VALUE self, VALUE sock) {
|
|
559
530
|
socklen_t len = (socklen_t)sizeof addr;
|
560
531
|
VALUE switchpoint_result = Qnil;
|
561
532
|
VALUE socket = Qnil;
|
562
|
-
VALUE underlying_sock = rb_ivar_get(
|
563
|
-
if (underlying_sock != Qnil)
|
533
|
+
VALUE underlying_sock = rb_ivar_get(server_socket, ID_ivar_io);
|
534
|
+
if (underlying_sock != Qnil) server_socket = underlying_sock;
|
564
535
|
|
565
536
|
GetBackend(self, backend);
|
566
|
-
GetOpenFile(
|
567
|
-
io_set_nonblock(fptr,
|
537
|
+
GetOpenFile(server_socket, fptr);
|
538
|
+
io_set_nonblock(fptr, server_socket);
|
568
539
|
watcher.fiber = Qnil;
|
569
540
|
|
570
541
|
while (1) {
|
@@ -586,7 +557,7 @@ VALUE Backend_accept_loop(VALUE self, VALUE sock) {
|
|
586
557
|
goto error;
|
587
558
|
}
|
588
559
|
|
589
|
-
socket = rb_obj_alloc(
|
560
|
+
socket = rb_obj_alloc(socket_class);
|
590
561
|
MakeOpenFile(socket, fp);
|
591
562
|
rb_update_max_fd(fd);
|
592
563
|
fp->fd = fd;
|
@@ -849,19 +820,12 @@ VALUE Backend_kind(VALUE self) {
|
|
849
820
|
void Init_Backend() {
|
850
821
|
ev_set_allocator(xrealloc);
|
851
822
|
|
852
|
-
rb_require("socket");
|
853
|
-
cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
854
|
-
|
855
823
|
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cData);
|
856
824
|
rb_define_alloc_func(cBackend, Backend_allocate);
|
857
825
|
|
858
826
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
859
827
|
rb_define_method(cBackend, "finalize", Backend_finalize, 0);
|
860
828
|
rb_define_method(cBackend, "post_fork", Backend_post_fork, 0);
|
861
|
-
rb_define_method(cBackend, "pending_count", Backend_pending_count, 0);
|
862
|
-
|
863
|
-
rb_define_method(cBackend, "ref", Backend_ref, 0);
|
864
|
-
rb_define_method(cBackend, "unref", Backend_unref, 0);
|
865
829
|
|
866
830
|
rb_define_method(cBackend, "poll", Backend_poll, 3);
|
867
831
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
@@ -869,8 +833,8 @@ void Init_Backend() {
|
|
869
833
|
rb_define_method(cBackend, "read", Backend_read, 4);
|
870
834
|
rb_define_method(cBackend, "read_loop", Backend_read_loop, 1);
|
871
835
|
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
872
|
-
rb_define_method(cBackend, "accept", Backend_accept,
|
873
|
-
rb_define_method(cBackend, "accept_loop", Backend_accept_loop,
|
836
|
+
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
837
|
+
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
874
838
|
rb_define_method(cBackend, "connect", Backend_connect, 3);
|
875
839
|
rb_define_method(cBackend, "recv", Backend_recv, 3);
|
876
840
|
rb_define_method(cBackend, "recv_loop", Backend_read_loop, 1);
|
@@ -886,15 +850,6 @@ void Init_Backend() {
|
|
886
850
|
|
887
851
|
ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
|
888
852
|
SYM_libev = ID2SYM(rb_intern("libev"));
|
889
|
-
|
890
|
-
__BACKEND__.pending_count = Backend_pending_count;
|
891
|
-
__BACKEND__.poll = Backend_poll;
|
892
|
-
__BACKEND__.ref = Backend_ref;
|
893
|
-
__BACKEND__.ref_count = Backend_ref_count;
|
894
|
-
__BACKEND__.reset_ref_count = Backend_reset_ref_count;
|
895
|
-
__BACKEND__.unref = Backend_unref;
|
896
|
-
__BACKEND__.wait_event = Backend_wait_event;
|
897
|
-
__BACKEND__.wakeup = Backend_wakeup;
|
898
853
|
}
|
899
854
|
|
900
855
|
#endif // POLYPHONY_BACKEND_LIBEV
|
data/ext/polyphony/event.c
CHANGED
@@ -66,7 +66,7 @@ VALUE Event_await(VALUE self) {
|
|
66
66
|
|
67
67
|
VALUE backend = rb_ivar_get(rb_thread_current(), ID_ivar_backend);
|
68
68
|
event->waiting_fiber = rb_fiber_current();
|
69
|
-
VALUE switchpoint_result =
|
69
|
+
VALUE switchpoint_result = Backend_wait_event(backend, Qnil);
|
70
70
|
event->waiting_fiber = Qnil;
|
71
71
|
|
72
72
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
data/ext/polyphony/polyphony.c
CHANGED
data/ext/polyphony/polyphony.h
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
#include <execinfo.h>
|
5
5
|
|
6
6
|
#include "ruby.h"
|
7
|
-
#include "backend.h"
|
8
7
|
#include "runqueue_ring_buffer.h"
|
9
8
|
|
10
9
|
// debugging
|
@@ -32,9 +31,6 @@
|
|
32
31
|
// Fiber#transfer
|
33
32
|
#define FIBER_TRANSFER(fiber, value) rb_funcall(fiber, ID_transfer, 1, value)
|
34
33
|
|
35
|
-
extern backend_interface_t backend_interface;
|
36
|
-
#define __BACKEND__ (backend_interface)
|
37
|
-
|
38
34
|
extern VALUE mPolyphony;
|
39
35
|
extern VALUE cQueue;
|
40
36
|
extern VALUE cEvent;
|
@@ -92,6 +88,11 @@ void Runqueue_clear(VALUE self);
|
|
92
88
|
long Runqueue_len(VALUE self);
|
93
89
|
int Runqueue_empty_p(VALUE self);
|
94
90
|
|
91
|
+
unsigned int Backend_pending_count(VALUE self);
|
92
|
+
VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue);
|
93
|
+
VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
|
94
|
+
VALUE Backend_wakeup(VALUE self);
|
95
|
+
|
95
96
|
VALUE Thread_schedule_fiber(VALUE thread, VALUE fiber, VALUE value);
|
96
97
|
VALUE Thread_schedule_fiber_with_priority(VALUE thread, VALUE fiber, VALUE value);
|
97
98
|
VALUE Thread_switch_fiber(VALUE thread);
|
data/ext/polyphony/queue.c
CHANGED
@@ -86,7 +86,7 @@ inline void capped_queue_block_push(Queue_t *queue) {
|
|
86
86
|
if (queue->capacity > queue->values.count) Fiber_make_runnable(fiber, Qnil);
|
87
87
|
|
88
88
|
ring_buffer_push(&queue->push_queue, fiber);
|
89
|
-
switchpoint_result =
|
89
|
+
switchpoint_result = Backend_wait_event(backend, Qnil);
|
90
90
|
ring_buffer_delete(&queue->push_queue, fiber);
|
91
91
|
|
92
92
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
@@ -131,7 +131,7 @@ VALUE Queue_shift(VALUE self) {
|
|
131
131
|
if (queue->values.count) Fiber_make_runnable(fiber, Qnil);
|
132
132
|
|
133
133
|
ring_buffer_push(&queue->shift_queue, fiber);
|
134
|
-
VALUE switchpoint_result =
|
134
|
+
VALUE switchpoint_result = Backend_wait_event(backend, Qnil);
|
135
135
|
ring_buffer_delete(&queue->shift_queue, fiber);
|
136
136
|
|
137
137
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
data/ext/polyphony/thread.c
CHANGED
@@ -17,16 +17,6 @@ static VALUE Thread_setup_fiber_scheduling(VALUE self) {
|
|
17
17
|
return self;
|
18
18
|
}
|
19
19
|
|
20
|
-
int Thread_fiber_ref_count(VALUE self) {
|
21
|
-
VALUE backend = rb_ivar_get(self, ID_ivar_backend);
|
22
|
-
return NUM2INT(__BACKEND__.ref_count(backend));
|
23
|
-
}
|
24
|
-
|
25
|
-
inline void Thread_fiber_reset_ref_count(VALUE self) {
|
26
|
-
VALUE backend = rb_ivar_get(self, ID_ivar_backend);
|
27
|
-
__BACKEND__.reset_ref_count(backend);
|
28
|
-
}
|
29
|
-
|
30
20
|
static VALUE SYM_scheduled_fibers;
|
31
21
|
static VALUE SYM_pending_watchers;
|
32
22
|
|
@@ -39,7 +29,7 @@ static VALUE Thread_fiber_scheduling_stats(VALUE self) {
|
|
39
29
|
long scheduled_count = Runqueue_len(runqueue);
|
40
30
|
rb_hash_aset(stats, SYM_scheduled_fibers, INT2NUM(scheduled_count));
|
41
31
|
|
42
|
-
pending_count =
|
32
|
+
pending_count = Backend_pending_count(backend);
|
43
33
|
rb_hash_aset(stats, SYM_pending_watchers, INT2NUM(pending_count));
|
44
34
|
|
45
35
|
return stats;
|
@@ -64,7 +54,7 @@ void schedule_fiber(VALUE self, VALUE fiber, VALUE value, int prioritize) {
|
|
64
54
|
// happen, not knowing that it there's already a fiber ready to run in its
|
65
55
|
// run queue.
|
66
56
|
VALUE backend = rb_ivar_get(self,ID_ivar_backend);
|
67
|
-
|
57
|
+
Backend_wakeup(backend);
|
68
58
|
}
|
69
59
|
}
|
70
60
|
}
|
@@ -84,25 +74,24 @@ VALUE Thread_switch_fiber(VALUE self) {
|
|
84
74
|
VALUE runqueue = rb_ivar_get(self, ID_ivar_runqueue);
|
85
75
|
runqueue_entry next;
|
86
76
|
VALUE backend = rb_ivar_get(self, ID_ivar_backend);
|
87
|
-
int
|
88
|
-
int backend_was_polled = 0;
|
77
|
+
unsigned int pending_count = Backend_pending_count(backend);
|
78
|
+
unsigned int backend_was_polled = 0;
|
89
79
|
|
90
80
|
if (__tracing_enabled__ && (rb_ivar_get(current_fiber, ID_ivar_running) != Qfalse))
|
91
81
|
TRACE(2, SYM_fiber_switchpoint, current_fiber);
|
92
82
|
|
93
|
-
ref_count = __BACKEND__.ref_count(backend);
|
94
83
|
while (1) {
|
95
84
|
next = Runqueue_shift(runqueue);
|
96
85
|
if (next.fiber != Qnil) {
|
97
|
-
if (backend_was_polled
|
86
|
+
if (!backend_was_polled && pending_count) {
|
98
87
|
// this prevents event starvation in case the run queue never empties
|
99
|
-
|
88
|
+
Backend_poll(backend, Qtrue, current_fiber, runqueue);
|
100
89
|
}
|
101
90
|
break;
|
102
91
|
}
|
103
|
-
if (
|
92
|
+
if (pending_count == 0) break;
|
104
93
|
|
105
|
-
|
94
|
+
Backend_poll(backend, Qnil, current_fiber, runqueue);
|
106
95
|
backend_was_polled = 1;
|
107
96
|
}
|
108
97
|
|
@@ -118,20 +107,13 @@ VALUE Thread_switch_fiber(VALUE self) {
|
|
118
107
|
next.value : FIBER_TRANSFER(next.fiber, next.value);
|
119
108
|
}
|
120
109
|
|
121
|
-
VALUE Thread_reset_fiber_scheduling(VALUE self) {
|
122
|
-
VALUE queue = rb_ivar_get(self, ID_ivar_runqueue);
|
123
|
-
Runqueue_clear(queue);
|
124
|
-
Thread_fiber_reset_ref_count(self);
|
125
|
-
return self;
|
126
|
-
}
|
127
|
-
|
128
110
|
VALUE Thread_fiber_schedule_and_wakeup(VALUE self, VALUE fiber, VALUE resume_obj) {
|
129
111
|
VALUE backend = rb_ivar_get(self, ID_ivar_backend);
|
130
112
|
if (fiber != Qnil) {
|
131
113
|
Thread_schedule_fiber_with_priority(self, fiber, resume_obj);
|
132
114
|
}
|
133
115
|
|
134
|
-
if (
|
116
|
+
if (Backend_wakeup(backend) == Qnil) {
|
135
117
|
// we're not inside the ev_loop, so we just do a switchpoint
|
136
118
|
Thread_switch_fiber(self);
|
137
119
|
}
|
@@ -146,7 +128,6 @@ VALUE Thread_debug(VALUE self) {
|
|
146
128
|
|
147
129
|
void Init_Thread() {
|
148
130
|
rb_define_method(rb_cThread, "setup_fiber_scheduling", Thread_setup_fiber_scheduling, 0);
|
149
|
-
rb_define_method(rb_cThread, "reset_fiber_scheduling", Thread_reset_fiber_scheduling, 0);
|
150
131
|
rb_define_method(rb_cThread, "fiber_scheduling_stats", Thread_fiber_scheduling_stats, 0);
|
151
132
|
rb_define_method(rb_cThread, "schedule_and_wakeup", Thread_fiber_schedule_and_wakeup, 2);
|
152
133
|
|
data/lib/polyphony.rb
CHANGED
@@ -14,6 +14,7 @@ Thread.current.backend = Polyphony::Backend.new
|
|
14
14
|
require_relative './polyphony/core/global_api'
|
15
15
|
require_relative './polyphony/core/resource_pool'
|
16
16
|
require_relative './polyphony/core/sync'
|
17
|
+
require_relative './polyphony/core/timer'
|
17
18
|
require_relative './polyphony/net'
|
18
19
|
require_relative './polyphony/adapters/process'
|
19
20
|
|
@@ -11,7 +11,7 @@ module ::PG
|
|
11
11
|
|
12
12
|
def self.connect_async(conn)
|
13
13
|
socket_io = conn.socket_io
|
14
|
-
|
14
|
+
while true
|
15
15
|
res = conn.connect_poll
|
16
16
|
case res
|
17
17
|
when PGRES_POLLING_FAILED then raise Error, conn.error_message
|
@@ -23,7 +23,7 @@ module ::PG
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.connect_sync(conn)
|
26
|
-
|
26
|
+
while true
|
27
27
|
res = conn.connect_poll
|
28
28
|
case res
|
29
29
|
when PGRES_POLLING_FAILED
|
@@ -96,7 +96,7 @@ class ::PG::Connection
|
|
96
96
|
def wait_for_notify(timeout = nil, &block)
|
97
97
|
return move_on_after(timeout) { wait_for_notify(&block) } if timeout
|
98
98
|
|
99
|
-
|
99
|
+
while true
|
100
100
|
Thread.current.backend.wait_io(socket_io, false)
|
101
101
|
consume_input
|
102
102
|
notice = notifies
|
@@ -59,7 +59,15 @@ module Polyphony
|
|
59
59
|
throttled_loop(rate: rate, interval: interval, &block)
|
60
60
|
end
|
61
61
|
else
|
62
|
-
|
62
|
+
spin_looped_block(tag, caller, block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def spin_looped_block(tag, caller, block)
|
67
|
+
Fiber.current.spin(tag, caller) do
|
68
|
+
block.call while true
|
69
|
+
rescue LocalJumpError, StopIteration
|
70
|
+
# break called or StopIteration raised
|
63
71
|
end
|
64
72
|
end
|
65
73
|
|
@@ -133,8 +141,12 @@ module Polyphony
|
|
133
141
|
if opts[:count]
|
134
142
|
opts[:count].times { |_i| throttler.(&block) }
|
135
143
|
else
|
136
|
-
|
144
|
+
while true
|
145
|
+
throttler.(&block)
|
146
|
+
end
|
137
147
|
end
|
148
|
+
rescue LocalJumpError, StopIteration
|
149
|
+
# break called or StopIteration raised
|
138
150
|
ensure
|
139
151
|
throttler&.stop
|
140
152
|
end
|