polyphony 0.43.9 → 0.43.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +1 -1
- data/TODO.md +1 -5
- data/ext/polyphony/agent.h +39 -0
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/libev_agent.c +65 -62
- data/ext/polyphony/polyphony.c +2 -0
- data/ext/polyphony/polyphony.h +7 -11
- data/ext/polyphony/queue.c +8 -1
- data/ext/polyphony/thread.c +33 -22
- data/lib/polyphony.rb +1 -1
- data/lib/polyphony/core/sync.rb +1 -1
- data/lib/polyphony/extensions/socket.rb +1 -9
- data/lib/polyphony/extensions/thread.rb +1 -1
- data/lib/polyphony/version.rb +1 -1
- data/test/helper.rb +1 -1
- data/test/test_agent.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3000a280d995b187518c1e12f585939b4e67312db5458d105c6e6b40c784d5a
|
4
|
+
data.tar.gz: 5a582fc77ae044238521619b1d5364a0dd2aac13ca8a6b82d006ec1f23284d2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d403109b1bbf55e1b0ab799d8c74752677784ca0c12cb5b1e21f62c9bdd244245966db8020b20a8d4ed988263a9535aef5a8aff24b50587c9583a67109d7677
|
7
|
+
data.tar.gz: 205d6c9859ec8d12ddf7630cbd3893a13d3efb3537dd734e53f17efe31d52399488761da45684d0da7e5074ce950c47a7e51f4a1446577e36f7c3c7838604a7a
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/TODO.md
CHANGED
@@ -1,8 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
-- Add `Fiber#schedule_with_priority` method, aliased by `Fiber#wakeup`
|
4
|
-
- Implement agent interface is virtual function table
|
5
|
-
- Implement proxy agent for plugging in a user-provided agent class
|
1
|
+
-- Add `Fiber#schedule_with_priority` method
|
6
2
|
|
7
3
|
- Debugging
|
8
4
|
- Eat your own dogfood: need a good tool to check what's going on when some
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#ifndef AGENT_H
|
2
|
+
#define AGENT_H
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
|
6
|
+
// agent interface function signatures
|
7
|
+
|
8
|
+
// VALUE LibevAgent_accept(VALUE self, VALUE sock);
|
9
|
+
// VALUE LibevAgent_accept_loop(VALUE self, VALUE sock);
|
10
|
+
// VALUE libev_agent_await(VALUE self);
|
11
|
+
// VALUE LibevAgent_connect(VALUE self, VALUE sock, VALUE host, VALUE port);
|
12
|
+
// VALUE LibevAgent_finalize(VALUE self);
|
13
|
+
// VALUE LibevAgent_post_fork(VALUE self);
|
14
|
+
// VALUE LibevAgent_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof);
|
15
|
+
// VALUE LibevAgent_read_loop(VALUE self, VALUE io);
|
16
|
+
// VALUE LibevAgent_ref(VALUE self);
|
17
|
+
// VALUE LibevAgent_sleep(VALUE self, VALUE duration);
|
18
|
+
// VALUE LibevAgent_unref(VALUE self);
|
19
|
+
// VALUE LibevAgent_wait_io(VALUE self, VALUE io, VALUE write);
|
20
|
+
// VALUE LibevAgent_wait_pid(VALUE self, VALUE pid);
|
21
|
+
// VALUE LibevAgent_write(int argc, VALUE *argv, VALUE self);
|
22
|
+
|
23
|
+
typedef VALUE (* agent_pending_count_t)(VALUE self);
|
24
|
+
typedef VALUE (*agent_poll_t)(VALUE self, VALUE nowait, VALUE current_fiber, VALUE queue);
|
25
|
+
typedef int (* agent_ref_count_t)(VALUE self);
|
26
|
+
typedef void (* agent_reset_ref_count_t)(VALUE self);
|
27
|
+
typedef VALUE (* agent_wait_event_t)(VALUE self, VALUE raise_on_exception);
|
28
|
+
typedef VALUE (* agent_wakeup_t)(VALUE self);
|
29
|
+
|
30
|
+
typedef struct agent_interface {
|
31
|
+
agent_pending_count_t pending_count;
|
32
|
+
agent_poll_t poll;
|
33
|
+
agent_ref_count_t ref_count;
|
34
|
+
agent_reset_ref_count_t reset_ref_count;
|
35
|
+
agent_wait_event_t wait_event;
|
36
|
+
agent_wakeup_t wakeup;
|
37
|
+
} agent_interface_t;
|
38
|
+
|
39
|
+
#endif /* AGENT_H */
|
data/ext/polyphony/event.c
CHANGED
@@ -66,7 +66,7 @@ VALUE Event_await(VALUE self) {
|
|
66
66
|
|
67
67
|
VALUE agent = rb_ivar_get(rb_thread_current(), ID_ivar_agent);
|
68
68
|
event->waiting_fiber = rb_fiber_current();
|
69
|
-
VALUE switchpoint_result =
|
69
|
+
VALUE switchpoint_result = __AGENT__.wait_event(agent, Qnil);
|
70
70
|
event->waiting_fiber = Qnil;
|
71
71
|
|
72
72
|
TEST_RESUME_EXCEPTION(switchpoint_result);
|
data/ext/polyphony/libev_agent.c
CHANGED
@@ -3,11 +3,12 @@
|
|
3
3
|
#include <sys/uio.h>
|
4
4
|
#include <unistd.h>
|
5
5
|
#include <fcntl.h>
|
6
|
+
#include <netinet/in.h>
|
7
|
+
#include <arpa/inet.h>
|
6
8
|
|
7
9
|
#include "polyphony.h"
|
8
10
|
#include "../libev/ev.h"
|
9
11
|
|
10
|
-
VALUE cLibevAgent = Qnil;
|
11
12
|
VALUE cTCPSocket;
|
12
13
|
|
13
14
|
struct LibevAgent_t {
|
@@ -150,7 +151,7 @@ VALUE LibevAgent_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE queue
|
|
150
151
|
return self;
|
151
152
|
}
|
152
153
|
|
153
|
-
VALUE
|
154
|
+
VALUE LibevAgent_wakeup(VALUE self) {
|
154
155
|
struct LibevAgent_t *agent;
|
155
156
|
GetLibevAgent(self, agent);
|
156
157
|
|
@@ -694,46 +695,41 @@ error:
|
|
694
695
|
return rb_funcall(rb_mKernel, ID_raise, 1, switchpoint_result);
|
695
696
|
}
|
696
697
|
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
// RB_GC_GUARD(switchpoint_result);
|
733
|
-
// return Qnil;
|
734
|
-
// error:
|
735
|
-
// return rb_funcall(rb_mKernel, ID_raise, 1, switchpoint_result);
|
736
|
-
// }
|
698
|
+
VALUE LibevAgent_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
699
|
+
struct LibevAgent_t *agent;
|
700
|
+
struct libev_io watcher;
|
701
|
+
rb_io_t *fptr;
|
702
|
+
struct sockaddr_in addr;
|
703
|
+
char *host_buf = StringValueCStr(host);
|
704
|
+
VALUE switchpoint_result = Qnil;
|
705
|
+
VALUE underlying_sock = rb_iv_get(sock, "@io");
|
706
|
+
if (underlying_sock != Qnil) sock = underlying_sock;
|
707
|
+
|
708
|
+
GetLibevAgent(self, agent);
|
709
|
+
GetOpenFile(sock, fptr);
|
710
|
+
io_set_nonblock(fptr, sock);
|
711
|
+
watcher.fiber = Qnil;
|
712
|
+
|
713
|
+
addr.sin_family = AF_INET;
|
714
|
+
addr.sin_addr.s_addr = inet_addr(host_buf);
|
715
|
+
addr.sin_port = htons(NUM2INT(port));
|
716
|
+
|
717
|
+
int result = connect(fptr->fd, (struct sockaddr *)&addr, sizeof(addr));
|
718
|
+
if (result < 0) {
|
719
|
+
int e = errno;
|
720
|
+
if (e != EINPROGRESS) rb_syserr_fail(e, strerror(e));
|
721
|
+
switchpoint_result = libev_io_wait(agent, &watcher, fptr, EV_WRITE);
|
722
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
723
|
+
}
|
724
|
+
else {
|
725
|
+
switchpoint_result = libev_snooze();
|
726
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
727
|
+
}
|
728
|
+
RB_GC_GUARD(switchpoint_result);
|
729
|
+
return sock;
|
730
|
+
error:
|
731
|
+
return rb_funcall(rb_mKernel, ID_raise, 1, switchpoint_result);
|
732
|
+
}
|
737
733
|
|
738
734
|
VALUE LibevAgent_wait_io(VALUE self, VALUE io, VALUE write) {
|
739
735
|
struct LibevAgent_t *agent;
|
@@ -853,30 +849,37 @@ void Init_LibevAgent() {
|
|
853
849
|
rb_require("socket");
|
854
850
|
cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
855
851
|
|
856
|
-
|
857
|
-
rb_define_alloc_func(
|
852
|
+
VALUE cAgent = rb_define_class_under(mPolyphony, "Agent", rb_cData);
|
853
|
+
rb_define_alloc_func(cAgent, LibevAgent_allocate);
|
858
854
|
|
859
|
-
rb_define_method(
|
860
|
-
rb_define_method(
|
861
|
-
rb_define_method(
|
862
|
-
rb_define_method(
|
855
|
+
rb_define_method(cAgent, "initialize", LibevAgent_initialize, 0);
|
856
|
+
rb_define_method(cAgent, "finalize", LibevAgent_finalize, 0);
|
857
|
+
rb_define_method(cAgent, "post_fork", LibevAgent_post_fork, 0);
|
858
|
+
rb_define_method(cAgent, "pending_count", LibevAgent_pending_count, 0);
|
863
859
|
|
864
|
-
rb_define_method(
|
865
|
-
rb_define_method(
|
860
|
+
rb_define_method(cAgent, "ref", LibevAgent_ref, 0);
|
861
|
+
rb_define_method(cAgent, "unref", LibevAgent_unref, 0);
|
866
862
|
|
867
|
-
rb_define_method(
|
868
|
-
rb_define_method(
|
863
|
+
rb_define_method(cAgent, "poll", LibevAgent_poll, 3);
|
864
|
+
rb_define_method(cAgent, "break", LibevAgent_wakeup, 0);
|
869
865
|
|
870
|
-
rb_define_method(
|
871
|
-
rb_define_method(
|
872
|
-
rb_define_method(
|
873
|
-
rb_define_method(
|
874
|
-
rb_define_method(
|
875
|
-
|
876
|
-
rb_define_method(
|
877
|
-
rb_define_method(
|
878
|
-
rb_define_method(
|
879
|
-
rb_define_method(
|
866
|
+
rb_define_method(cAgent, "read", LibevAgent_read, 4);
|
867
|
+
rb_define_method(cAgent, "read_loop", LibevAgent_read_loop, 1);
|
868
|
+
rb_define_method(cAgent, "write", LibevAgent_write_m, -1);
|
869
|
+
rb_define_method(cAgent, "accept", LibevAgent_accept, 1);
|
870
|
+
rb_define_method(cAgent, "accept_loop", LibevAgent_accept_loop, 1);
|
871
|
+
rb_define_method(cAgent, "connect", LibevAgent_connect, 3);
|
872
|
+
rb_define_method(cAgent, "wait_io", LibevAgent_wait_io, 2);
|
873
|
+
rb_define_method(cAgent, "sleep", LibevAgent_sleep, 1);
|
874
|
+
rb_define_method(cAgent, "waitpid", LibevAgent_waitpid, 1);
|
875
|
+
rb_define_method(cAgent, "wait_event", LibevAgent_wait_event, 1);
|
880
876
|
|
881
877
|
ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
|
878
|
+
|
879
|
+
__AGENT__.wakeup = LibevAgent_wakeup;
|
880
|
+
__AGENT__.pending_count = LibevAgent_pending_count;
|
881
|
+
__AGENT__.poll = LibevAgent_poll;
|
882
|
+
__AGENT__.ref_count = LibevAgent_ref_count;
|
883
|
+
__AGENT__.reset_ref_count = LibevAgent_reset_ref_count;
|
884
|
+
__AGENT__.wait_event = LibevAgent_wait_event;
|
882
885
|
}
|
data/ext/polyphony/polyphony.c
CHANGED
data/ext/polyphony/polyphony.h
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
#include "ruby.h"
|
5
5
|
#include "ruby/io.h"
|
6
6
|
#include "libev.h"
|
7
|
+
#include "agent.h"
|
7
8
|
|
8
9
|
// debugging
|
9
10
|
#define OBJ_ID(obj) (NUM2LONG(rb_funcall(obj, rb_intern("object_id"), 0)))
|
@@ -18,6 +19,12 @@
|
|
18
19
|
return rb_funcall(rb_mKernel, ID_raise, 1, ret); \
|
19
20
|
}
|
20
21
|
|
22
|
+
extern agent_interface_t agent_interface;
|
23
|
+
// #define __AGENT_PASTER__(call) (agent_interface ## . ## call)
|
24
|
+
// #define __AGENT__(call) __AGENT_PASTER__(call)
|
25
|
+
#define __AGENT__ (agent_interface)
|
26
|
+
|
27
|
+
|
21
28
|
extern VALUE mPolyphony;
|
22
29
|
extern VALUE cQueue;
|
23
30
|
extern VALUE cEvent;
|
@@ -65,17 +72,6 @@ enum {
|
|
65
72
|
VALUE Fiber_auto_watcher(VALUE self);
|
66
73
|
void Fiber_make_runnable(VALUE fiber, VALUE value);
|
67
74
|
|
68
|
-
VALUE LibevAgent_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE queue);
|
69
|
-
VALUE LibevAgent_break(VALUE self);
|
70
|
-
VALUE LibevAgent_pending_count(VALUE self);
|
71
|
-
VALUE LibevAgent_wait_io(VALUE self, VALUE io, VALUE write);
|
72
|
-
|
73
|
-
VALUE LibevAgent_ref(VALUE self);
|
74
|
-
VALUE LibevAgent_unref(VALUE self);
|
75
|
-
int LibevAgent_ref_count(VALUE self);
|
76
|
-
void LibevAgent_reset_ref_count(VALUE self);
|
77
|
-
VALUE LibevAgent_wait_event(VALUE self, VALUE raise);
|
78
|
-
|
79
75
|
VALUE Queue_push(VALUE self, VALUE value);
|
80
76
|
VALUE Queue_unshift(VALUE self, VALUE value);
|
81
77
|
VALUE Queue_shift(VALUE self);
|
data/ext/polyphony/queue.c
CHANGED
@@ -82,7 +82,7 @@ VALUE Queue_shift(VALUE self) {
|
|
82
82
|
VALUE fiber = rb_fiber_current();
|
83
83
|
VALUE switchpoint_result = Qnil;
|
84
84
|
ring_buffer_push(&queue->shift_queue, fiber);
|
85
|
-
switchpoint_result =
|
85
|
+
switchpoint_result = __AGENT__.wait_event(agent, Qnil);
|
86
86
|
if (RTEST(rb_obj_is_kind_of(switchpoint_result, rb_eException))) {
|
87
87
|
ring_buffer_delete(&queue->shift_queue, fiber);
|
88
88
|
return rb_funcall(rb_mKernel, ID_raise, 1, switchpoint_result);
|
@@ -165,6 +165,13 @@ VALUE Queue_size_m(VALUE self) {
|
|
165
165
|
return INT2NUM(queue->values.count);
|
166
166
|
}
|
167
167
|
|
168
|
+
void Queue_trace(VALUE self) {
|
169
|
+
Queue_t *queue;
|
170
|
+
GetQueue(self, queue);
|
171
|
+
|
172
|
+
printf("run queue size: %d count: %d\n", queue->values.size, queue->values.count);
|
173
|
+
}
|
174
|
+
|
168
175
|
void Init_Queue() {
|
169
176
|
cQueue = rb_define_class_under(mPolyphony, "Queue", rb_cData);
|
170
177
|
rb_define_alloc_func(cQueue, Queue_allocate);
|
data/ext/polyphony/thread.c
CHANGED
@@ -21,12 +21,12 @@ static VALUE Thread_setup_fiber_scheduling(VALUE self) {
|
|
21
21
|
|
22
22
|
int Thread_fiber_ref_count(VALUE self) {
|
23
23
|
VALUE agent = rb_ivar_get(self, ID_ivar_agent);
|
24
|
-
return NUM2INT(
|
24
|
+
return NUM2INT(__AGENT__.ref_count(agent));
|
25
25
|
}
|
26
26
|
|
27
27
|
inline void Thread_fiber_reset_ref_count(VALUE self) {
|
28
28
|
VALUE agent = rb_ivar_get(self, ID_ivar_agent);
|
29
|
-
|
29
|
+
__AGENT__.reset_ref_count(agent);
|
30
30
|
}
|
31
31
|
|
32
32
|
static VALUE SYM_scheduled_fibers;
|
@@ -41,7 +41,7 @@ static VALUE Thread_fiber_scheduling_stats(VALUE self) {
|
|
41
41
|
long scheduled_count = RARRAY_LEN(queue);
|
42
42
|
rb_hash_aset(stats, SYM_scheduled_fibers, INT2NUM(scheduled_count));
|
43
43
|
|
44
|
-
pending_count =
|
44
|
+
pending_count = __AGENT__.pending_count(agent);
|
45
45
|
rb_hash_aset(stats, SYM_pending_watchers, INT2NUM(pending_count));
|
46
46
|
|
47
47
|
return stats;
|
@@ -52,23 +52,34 @@ VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
|
|
52
52
|
|
53
53
|
if (rb_fiber_alive_p(fiber) != Qtrue) return self;
|
54
54
|
|
55
|
-
|
55
|
+
int already_runnable = rb_ivar_get(fiber, ID_runnable) != Qnil;
|
56
|
+
|
57
|
+
if (already_runnable) {
|
58
|
+
VALUE current_runnable_value = rb_ivar_get(fiber, ID_runnable_value);
|
59
|
+
|
60
|
+
// If the fiber is already runnable and the runnable value is an exception,
|
61
|
+
// we don't update the value, in order to prevent a race condition where
|
62
|
+
// exceptions will be lost (see issue #33)
|
63
|
+
if (TEST_EXCEPTION(current_runnable_value)) return self;
|
64
|
+
}
|
65
|
+
|
56
66
|
rb_ivar_set(fiber, ID_runnable_value, value);
|
57
|
-
|
58
|
-
if (rb_ivar_get(fiber, ID_runnable) != Qnil) return self;
|
67
|
+
FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
|
59
68
|
|
60
|
-
|
61
|
-
|
62
|
-
|
69
|
+
if (!already_runnable) {
|
70
|
+
queue = rb_ivar_get(self, ID_run_queue);
|
71
|
+
Queue_push(queue, fiber);
|
72
|
+
rb_ivar_set(fiber, ID_runnable, Qtrue);
|
63
73
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
74
|
+
if (rb_thread_current() != self) {
|
75
|
+
// If the fiber scheduling is done across threads, we need to make sure the
|
76
|
+
// target thread is woken up in case it is in the middle of running its
|
77
|
+
// event selector. Otherwise it's gonna be stuck waiting for an event to
|
78
|
+
// happen, not knowing that it there's already a fiber ready to run in its
|
79
|
+
// run queue.
|
80
|
+
VALUE agent = rb_ivar_get(self,ID_ivar_agent);
|
81
|
+
__AGENT__.wakeup(agent);
|
82
|
+
}
|
72
83
|
}
|
73
84
|
return self;
|
74
85
|
}
|
@@ -100,7 +111,7 @@ VALUE Thread_schedule_fiber_with_priority(VALUE self, VALUE fiber, VALUE value)
|
|
100
111
|
// happen, not knowing that it there's already a fiber ready to run in its
|
101
112
|
// run queue.
|
102
113
|
VALUE agent = rb_ivar_get(self, ID_ivar_agent);
|
103
|
-
|
114
|
+
__AGENT__.wakeup(agent);
|
104
115
|
}
|
105
116
|
return self;
|
106
117
|
}
|
@@ -120,20 +131,20 @@ VALUE Thread_switch_fiber(VALUE self) {
|
|
120
131
|
}
|
121
132
|
}
|
122
133
|
|
123
|
-
ref_count =
|
134
|
+
ref_count = __AGENT__.ref_count(agent);
|
124
135
|
while (1) {
|
125
136
|
next_fiber = Queue_shift_no_wait(queue);
|
126
137
|
if (next_fiber != Qnil) {
|
127
138
|
if (agent_was_polled == 0 && ref_count > 0) {
|
128
139
|
// this mechanism prevents event starvation in case the run queue never
|
129
140
|
// empties
|
130
|
-
|
141
|
+
__AGENT__.poll(agent, Qtrue, current_fiber, queue);
|
131
142
|
}
|
132
143
|
break;
|
133
144
|
}
|
134
145
|
if (ref_count == 0) break;
|
135
146
|
|
136
|
-
|
147
|
+
__AGENT__.poll(agent, Qnil, current_fiber, queue);
|
137
148
|
agent_was_polled = 1;
|
138
149
|
}
|
139
150
|
|
@@ -169,7 +180,7 @@ VALUE Thread_fiber_break_out_of_ev_loop(VALUE self, VALUE fiber, VALUE resume_ob
|
|
169
180
|
Thread_schedule_fiber_with_priority(self, fiber, resume_obj);
|
170
181
|
}
|
171
182
|
|
172
|
-
if (
|
183
|
+
if (__AGENT__.wakeup(agent) == Qnil) {
|
173
184
|
// we're not inside the ev_loop, so we just do a switchpoint
|
174
185
|
Thread_switch_fiber(self);
|
175
186
|
}
|
data/lib/polyphony.rb
CHANGED
@@ -17,7 +17,7 @@ require_relative './polyphony/extensions/fiber'
|
|
17
17
|
require_relative './polyphony/extensions/io'
|
18
18
|
|
19
19
|
Thread.current.setup_fiber_scheduling
|
20
|
-
Thread.current.agent = Polyphony::
|
20
|
+
Thread.current.agent = Polyphony::Agent.new
|
21
21
|
|
22
22
|
require_relative './polyphony/core/global_api'
|
23
23
|
require_relative './polyphony/core/resource_pool'
|
data/lib/polyphony/core/sync.rb
CHANGED
@@ -24,15 +24,7 @@ class ::Socket
|
|
24
24
|
NO_EXCEPTION = { exception: false }.freeze
|
25
25
|
|
26
26
|
def connect(remotesockaddr)
|
27
|
-
|
28
|
-
result = connect_nonblock(remotesockaddr, **NO_EXCEPTION)
|
29
|
-
case result
|
30
|
-
when 0 then return
|
31
|
-
when :wait_writable then Thread.current.agent.wait_io(self, true)
|
32
|
-
else
|
33
|
-
raise IOError
|
34
|
-
end
|
35
|
-
end
|
27
|
+
Thread.current.agent.connect(self, remotesockaddr.ip_address, remotesockaddr.ip_port)
|
36
28
|
end
|
37
29
|
|
38
30
|
def recv(maxlen, flags = 0, outbuf = nil)
|
@@ -18,7 +18,7 @@ class ::Thread
|
|
18
18
|
def execute
|
19
19
|
# agent must be created in the context of the new thread, therefore it
|
20
20
|
# cannot be created in Thread#initialize
|
21
|
-
@agent = Polyphony::
|
21
|
+
@agent = Polyphony::Agent.new
|
22
22
|
setup
|
23
23
|
@ready = true
|
24
24
|
result = @block.(*@args)
|
data/lib/polyphony/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -31,7 +31,7 @@ class MiniTest::Test
|
|
31
31
|
end
|
32
32
|
Fiber.current.setup_main_fiber
|
33
33
|
Fiber.current.instance_variable_set(:@auto_watcher, nil)
|
34
|
-
Thread.current.agent = Polyphony::
|
34
|
+
Thread.current.agent = Polyphony::Agent.new
|
35
35
|
sleep 0 # apparently this helps with timer accuracy
|
36
36
|
end
|
37
37
|
|
data/test/test_agent.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: polyphony
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.43.
|
4
|
+
version: 0.43.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-07-
|
11
|
+
date: 2020-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -389,6 +389,7 @@ files:
|
|
389
389
|
- ext/libev/ev_win32.c
|
390
390
|
- ext/libev/ev_wrap.h
|
391
391
|
- ext/libev/test_libev_win32.c
|
392
|
+
- ext/polyphony/agent.h
|
392
393
|
- ext/polyphony/event.c
|
393
394
|
- ext/polyphony/extconf.rb
|
394
395
|
- ext/polyphony/fiber.c
|
@@ -476,7 +477,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
476
477
|
- !ruby/object:Gem::Version
|
477
478
|
version: '0'
|
478
479
|
requirements: []
|
479
|
-
rubygems_version: 3.
|
480
|
+
rubygems_version: 3.0.8
|
480
481
|
signing_key:
|
481
482
|
specification_version: 4
|
482
483
|
summary: Fine grained concurrency for Ruby
|