polyphony 0.47.5.1 → 0.50.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 +29 -0
- data/Gemfile.lock +1 -1
- data/LICENSE +1 -1
- data/TODO.md +37 -17
- data/examples/core/nested.rb +21 -0
- data/examples/core/suspend.rb +13 -0
- data/examples/core/terminate_main_fiber.rb +12 -0
- data/examples/io/tcp_proxy.rb +32 -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 -2
- data/ext/polyphony/backend_common.h +3 -3
- data/ext/polyphony/backend_io_uring.c +29 -68
- data/ext/polyphony/backend_libev.c +18 -59
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/fiber.c +2 -1
- data/ext/polyphony/polyphony.c +0 -2
- data/ext/polyphony/polyphony.h +6 -4
- data/ext/polyphony/queue.c +2 -2
- data/ext/polyphony/runqueue.c +6 -0
- data/ext/polyphony/runqueue_ring_buffer.c +9 -0
- data/ext/polyphony/runqueue_ring_buffer.h +1 -0
- data/ext/polyphony/thread.c +23 -28
- data/lib/polyphony.rb +2 -1
- data/lib/polyphony/adapters/postgres.rb +3 -3
- data/lib/polyphony/adapters/process.rb +2 -0
- data/lib/polyphony/core/exceptions.rb +1 -0
- data/lib/polyphony/core/global_api.rb +15 -3
- data/lib/polyphony/core/thread_pool.rb +3 -1
- data/lib/polyphony/core/throttler.rb +1 -1
- data/lib/polyphony/core/timer.rb +115 -0
- data/lib/polyphony/extensions/core.rb +4 -4
- data/lib/polyphony/extensions/fiber.rb +30 -13
- data/lib/polyphony/extensions/io.rb +8 -14
- data/lib/polyphony/extensions/openssl.rb +4 -4
- data/lib/polyphony/extensions/socket.rb +1 -1
- data/lib/polyphony/extensions/thread.rb +1 -2
- data/lib/polyphony/net.rb +3 -6
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -1
- data/test/helper.rb +2 -2
- data/test/test_backend.rb +26 -1
- data/test/test_fiber.rb +95 -1
- data/test/test_global_api.rb +30 -0
- data/test/test_io.rb +26 -0
- data/test/test_signal.rb +1 -2
- data/test/test_socket.rb +5 -5
- data/test/test_supervise.rb +1 -1
- data/test/test_timer.rb +157 -0
- metadata +11 -4
- data/ext/polyphony/backend.h +0 -26
@@ -40,11 +40,14 @@ inline void io_set_nonblock(rb_io_t *fptr, VALUE io) {
|
|
40
40
|
}
|
41
41
|
|
42
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
|
43
49
|
struct ev_loop *ev_loop;
|
44
50
|
struct ev_async break_async;
|
45
|
-
int running;
|
46
|
-
int ref_count;
|
47
|
-
int run_no_wait_count;
|
48
51
|
} Backend_t;
|
49
52
|
|
50
53
|
static size_t Backend_size(const void *ptr) {
|
@@ -83,9 +86,9 @@ static VALUE Backend_initialize(VALUE self) {
|
|
83
86
|
ev_async_start(backend->ev_loop, &backend->break_async);
|
84
87
|
ev_unref(backend->ev_loop); // don't count the break_async watcher
|
85
88
|
|
86
|
-
backend->
|
87
|
-
backend->
|
88
|
-
backend->
|
89
|
+
backend->currently_polling = 0;
|
90
|
+
backend->pending_count = 0;
|
91
|
+
backend->poll_no_wait_count = 0;
|
89
92
|
|
90
93
|
return Qnil;
|
91
94
|
}
|
@@ -116,42 +119,11 @@ VALUE Backend_post_fork(VALUE self) {
|
|
116
119
|
return self;
|
117
120
|
}
|
118
121
|
|
119
|
-
|
120
|
-
Backend_t *backend;
|
121
|
-
GetBackend(self, backend);
|
122
|
-
|
123
|
-
backend->ref_count++;
|
124
|
-
return self;
|
125
|
-
}
|
126
|
-
|
127
|
-
VALUE Backend_unref(VALUE self) {
|
128
|
-
Backend_t *backend;
|
129
|
-
GetBackend(self, backend);
|
130
|
-
|
131
|
-
backend->ref_count--;
|
132
|
-
return self;
|
133
|
-
}
|
134
|
-
|
135
|
-
int Backend_ref_count(VALUE self) {
|
136
|
-
Backend_t *backend;
|
137
|
-
GetBackend(self, backend);
|
138
|
-
|
139
|
-
return backend->ref_count;
|
140
|
-
}
|
141
|
-
|
142
|
-
void Backend_reset_ref_count(VALUE self) {
|
122
|
+
unsigned int Backend_pending_count(VALUE self) {
|
143
123
|
Backend_t *backend;
|
144
124
|
GetBackend(self, backend);
|
145
125
|
|
146
|
-
backend->
|
147
|
-
}
|
148
|
-
|
149
|
-
VALUE Backend_pending_count(VALUE self) {
|
150
|
-
int count;
|
151
|
-
Backend_t *backend;
|
152
|
-
GetBackend(self, backend);
|
153
|
-
count = ev_pending_count(backend->ev_loop);
|
154
|
-
return INT2NUM(count);
|
126
|
+
return backend->pending_count;
|
155
127
|
}
|
156
128
|
|
157
129
|
VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue) {
|
@@ -160,19 +132,19 @@ VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue
|
|
160
132
|
GetBackend(self, backend);
|
161
133
|
|
162
134
|
if (is_nowait) {
|
163
|
-
backend->
|
164
|
-
if (backend->
|
135
|
+
backend->poll_no_wait_count++;
|
136
|
+
if (backend->poll_no_wait_count < 10) return self;
|
165
137
|
|
166
138
|
long runnable_count = Runqueue_len(runqueue);
|
167
|
-
if (backend->
|
139
|
+
if (backend->poll_no_wait_count < runnable_count) return self;
|
168
140
|
}
|
169
141
|
|
170
|
-
backend->
|
142
|
+
backend->poll_no_wait_count = 0;
|
171
143
|
|
172
144
|
COND_TRACE(2, SYM_fiber_event_poll_enter, current_fiber);
|
173
|
-
backend->
|
145
|
+
backend->currently_polling = 1;
|
174
146
|
ev_run(backend->ev_loop, is_nowait ? EVRUN_NOWAIT : EVRUN_ONCE);
|
175
|
-
backend->
|
147
|
+
backend->currently_polling = 0;
|
176
148
|
COND_TRACE(2, SYM_fiber_event_poll_leave, current_fiber);
|
177
149
|
|
178
150
|
return self;
|
@@ -182,7 +154,7 @@ VALUE Backend_wakeup(VALUE self) {
|
|
182
154
|
Backend_t *backend;
|
183
155
|
GetBackend(self, backend);
|
184
156
|
|
185
|
-
if (backend->
|
157
|
+
if (backend->currently_polling) {
|
186
158
|
// Since the loop will run until at least one event has occurred, we signal
|
187
159
|
// the selector's associated async watcher, which will cause the ev loop to
|
188
160
|
// return. In contrast to using `ev_break` to break out of the loop, which
|
@@ -854,10 +826,6 @@ void Init_Backend() {
|
|
854
826
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
855
827
|
rb_define_method(cBackend, "finalize", Backend_finalize, 0);
|
856
828
|
rb_define_method(cBackend, "post_fork", Backend_post_fork, 0);
|
857
|
-
rb_define_method(cBackend, "pending_count", Backend_pending_count, 0);
|
858
|
-
|
859
|
-
rb_define_method(cBackend, "ref", Backend_ref, 0);
|
860
|
-
rb_define_method(cBackend, "unref", Backend_unref, 0);
|
861
829
|
|
862
830
|
rb_define_method(cBackend, "poll", Backend_poll, 3);
|
863
831
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
@@ -882,15 +850,6 @@ void Init_Backend() {
|
|
882
850
|
|
883
851
|
ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
|
884
852
|
SYM_libev = ID2SYM(rb_intern("libev"));
|
885
|
-
|
886
|
-
__BACKEND__.pending_count = Backend_pending_count;
|
887
|
-
__BACKEND__.poll = Backend_poll;
|
888
|
-
__BACKEND__.ref = Backend_ref;
|
889
|
-
__BACKEND__.ref_count = Backend_ref_count;
|
890
|
-
__BACKEND__.reset_ref_count = Backend_reset_ref_count;
|
891
|
-
__BACKEND__.unref = Backend_unref;
|
892
|
-
__BACKEND__.wait_event = Backend_wait_event;
|
893
|
-
__BACKEND__.wakeup = Backend_wakeup;
|
894
853
|
}
|
895
854
|
|
896
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/fiber.c
CHANGED
@@ -101,7 +101,8 @@ VALUE Fiber_await(VALUE self) {
|
|
101
101
|
}
|
102
102
|
rb_hash_aset(waiting_fibers, fiber, Qtrue);
|
103
103
|
|
104
|
-
|
104
|
+
VALUE backend = rb_ivar_get(rb_thread_current(), ID_ivar_backend);
|
105
|
+
result = Backend_wait_event(backend, Qnil);
|
105
106
|
|
106
107
|
rb_hash_delete(waiting_fibers, fiber);
|
107
108
|
RAISE_IF_EXCEPTION(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;
|
@@ -88,10 +84,16 @@ void Runqueue_push(VALUE self, VALUE fiber, VALUE value, int reschedule);
|
|
88
84
|
void Runqueue_unshift(VALUE self, VALUE fiber, VALUE value, int reschedule);
|
89
85
|
runqueue_entry Runqueue_shift(VALUE self);
|
90
86
|
void Runqueue_delete(VALUE self, VALUE fiber);
|
87
|
+
int Runqueue_index_of(VALUE self, VALUE fiber);
|
91
88
|
void Runqueue_clear(VALUE self);
|
92
89
|
long Runqueue_len(VALUE self);
|
93
90
|
int Runqueue_empty_p(VALUE self);
|
94
91
|
|
92
|
+
unsigned int Backend_pending_count(VALUE self);
|
93
|
+
VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue);
|
94
|
+
VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
|
95
|
+
VALUE Backend_wakeup(VALUE self);
|
96
|
+
|
95
97
|
VALUE Thread_schedule_fiber(VALUE thread, VALUE fiber, VALUE value);
|
96
98
|
VALUE Thread_schedule_fiber_with_priority(VALUE thread, VALUE fiber, VALUE value);
|
97
99
|
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/runqueue.c
CHANGED
@@ -74,6 +74,12 @@ void Runqueue_delete(VALUE self, VALUE fiber) {
|
|
74
74
|
runqueue_ring_buffer_delete(&runqueue->entries, fiber);
|
75
75
|
}
|
76
76
|
|
77
|
+
int Runqueue_index_of(VALUE self, VALUE fiber) {
|
78
|
+
Runqueue_t *runqueue;
|
79
|
+
GetRunqueue(self, runqueue);
|
80
|
+
return runqueue_ring_buffer_index_of(&runqueue->entries, fiber);
|
81
|
+
}
|
82
|
+
|
77
83
|
void Runqueue_clear(VALUE self) {
|
78
84
|
Runqueue_t *runqueue;
|
79
85
|
GetRunqueue(self, runqueue);
|
@@ -80,6 +80,15 @@ void runqueue_ring_buffer_delete(runqueue_ring_buffer *buffer, VALUE fiber) {
|
|
80
80
|
}
|
81
81
|
}
|
82
82
|
|
83
|
+
int runqueue_ring_buffer_index_of(runqueue_ring_buffer *buffer, VALUE fiber) {
|
84
|
+
for (unsigned int i = 0; i < buffer->count; i++) {
|
85
|
+
unsigned int idx = (buffer->head + i) % buffer->size;
|
86
|
+
if (buffer->entries[idx].fiber == fiber)
|
87
|
+
return i;
|
88
|
+
}
|
89
|
+
return -1;
|
90
|
+
}
|
91
|
+
|
83
92
|
void runqueue_ring_buffer_clear(runqueue_ring_buffer *buffer) {
|
84
93
|
buffer->count = buffer->head = buffer->tail = 0;
|
85
94
|
}
|
@@ -27,5 +27,6 @@ void runqueue_ring_buffer_unshift(runqueue_ring_buffer *buffer, VALUE fiber, VAL
|
|
27
27
|
void runqueue_ring_buffer_push(runqueue_ring_buffer *buffer, VALUE fiber, VALUE value);
|
28
28
|
|
29
29
|
void runqueue_ring_buffer_delete(runqueue_ring_buffer *buffer, VALUE fiber);
|
30
|
+
int runqueue_ring_buffer_index_of(runqueue_ring_buffer *buffer, VALUE fiber);
|
30
31
|
|
31
32
|
#endif /* RUNQUEUE_RING_BUFFER_H */
|
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,11 +54,23 @@ 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
|
}
|
71
61
|
|
62
|
+
VALUE Thread_fiber_scheduling_index(VALUE self, VALUE fiber) {
|
63
|
+
VALUE runqueue = rb_ivar_get(self, ID_ivar_runqueue);
|
64
|
+
|
65
|
+
return INT2NUM(Runqueue_index_of(runqueue, fiber));
|
66
|
+
}
|
67
|
+
|
68
|
+
VALUE Thread_fiber_unschedule(VALUE self, VALUE fiber) {
|
69
|
+
VALUE runqueue = rb_ivar_get(self, ID_ivar_runqueue);
|
70
|
+
Runqueue_delete(runqueue, fiber);
|
71
|
+
return self;
|
72
|
+
}
|
73
|
+
|
72
74
|
VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
|
73
75
|
schedule_fiber(self, fiber, value, 0);
|
74
76
|
return self;
|
@@ -84,25 +86,24 @@ VALUE Thread_switch_fiber(VALUE self) {
|
|
84
86
|
VALUE runqueue = rb_ivar_get(self, ID_ivar_runqueue);
|
85
87
|
runqueue_entry next;
|
86
88
|
VALUE backend = rb_ivar_get(self, ID_ivar_backend);
|
87
|
-
int
|
88
|
-
int backend_was_polled = 0;
|
89
|
+
unsigned int pending_count = Backend_pending_count(backend);
|
90
|
+
unsigned int backend_was_polled = 0;
|
89
91
|
|
90
92
|
if (__tracing_enabled__ && (rb_ivar_get(current_fiber, ID_ivar_running) != Qfalse))
|
91
93
|
TRACE(2, SYM_fiber_switchpoint, current_fiber);
|
92
94
|
|
93
|
-
ref_count = __BACKEND__.ref_count(backend);
|
94
95
|
while (1) {
|
95
96
|
next = Runqueue_shift(runqueue);
|
96
97
|
if (next.fiber != Qnil) {
|
97
|
-
if (backend_was_polled
|
98
|
+
if (!backend_was_polled && pending_count) {
|
98
99
|
// this prevents event starvation in case the run queue never empties
|
99
|
-
|
100
|
+
Backend_poll(backend, Qtrue, current_fiber, runqueue);
|
100
101
|
}
|
101
102
|
break;
|
102
103
|
}
|
103
|
-
if (
|
104
|
+
if (pending_count == 0) break;
|
104
105
|
|
105
|
-
|
106
|
+
Backend_poll(backend, Qnil, current_fiber, runqueue);
|
106
107
|
backend_was_polled = 1;
|
107
108
|
}
|
108
109
|
|
@@ -118,20 +119,13 @@ VALUE Thread_switch_fiber(VALUE self) {
|
|
118
119
|
next.value : FIBER_TRANSFER(next.fiber, next.value);
|
119
120
|
}
|
120
121
|
|
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
122
|
VALUE Thread_fiber_schedule_and_wakeup(VALUE self, VALUE fiber, VALUE resume_obj) {
|
129
123
|
VALUE backend = rb_ivar_get(self, ID_ivar_backend);
|
130
124
|
if (fiber != Qnil) {
|
131
125
|
Thread_schedule_fiber_with_priority(self, fiber, resume_obj);
|
132
126
|
}
|
133
127
|
|
134
|
-
if (
|
128
|
+
if (Backend_wakeup(backend) == Qnil) {
|
135
129
|
// we're not inside the ev_loop, so we just do a switchpoint
|
136
130
|
Thread_switch_fiber(self);
|
137
131
|
}
|
@@ -146,7 +140,6 @@ VALUE Thread_debug(VALUE self) {
|
|
146
140
|
|
147
141
|
void Init_Thread() {
|
148
142
|
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
143
|
rb_define_method(rb_cThread, "fiber_scheduling_stats", Thread_fiber_scheduling_stats, 0);
|
151
144
|
rb_define_method(rb_cThread, "schedule_and_wakeup", Thread_fiber_schedule_and_wakeup, 2);
|
152
145
|
|
@@ -154,6 +147,8 @@ void Init_Thread() {
|
|
154
147
|
rb_define_method(rb_cThread, "schedule_fiber_with_priority",
|
155
148
|
Thread_schedule_fiber_with_priority, 2);
|
156
149
|
rb_define_method(rb_cThread, "switch_fiber", Thread_switch_fiber, 0);
|
150
|
+
rb_define_method(rb_cThread, "fiber_scheduling_index", Thread_fiber_scheduling_index, 1);
|
151
|
+
rb_define_method(rb_cThread, "fiber_unschedule", Thread_fiber_unschedule, 1);
|
157
152
|
|
158
153
|
rb_define_method(rb_cThread, "debug!", Thread_debug, 0);
|
159
154
|
|
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
|
|
@@ -43,7 +44,7 @@ module Polyphony
|
|
43
44
|
rescue SystemExit
|
44
45
|
# fall through to ensure
|
45
46
|
rescue Exception => e
|
46
|
-
|
47
|
+
STDERR << e.full_message
|
47
48
|
exit!
|
48
49
|
ensure
|
49
50
|
exit_forked_process
|
@@ -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
|
@@ -29,7 +29,7 @@ module Polyphony
|
|
29
29
|
spin do
|
30
30
|
sleep interval
|
31
31
|
exception = cancel_exception(with_exception)
|
32
|
-
exception.
|
32
|
+
exception.raising_fiber = nil
|
33
33
|
fiber.schedule exception
|
34
34
|
end
|
35
35
|
end
|
@@ -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
|