polyphony 0.43.9 → 0.43.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14930ef46f39537ad6f2233b23691a05d910ecf6c22cd8429a8a82dcf4f2af51
4
- data.tar.gz: a2c53e7082c35025cce3024113162ed5e67032eed82d49c363516441c3293898
3
+ metadata.gz: b3000a280d995b187518c1e12f585939b4e67312db5458d105c6e6b40c784d5a
4
+ data.tar.gz: 5a582fc77ae044238521619b1d5364a0dd2aac13ca8a6b82d006ec1f23284d2d
5
5
  SHA512:
6
- metadata.gz: ac9d80b5a0fad4b4d164bed60c42d386fc49e978b381a2a9fd6174bf616cb5a97cb4232c317c62ac0439f534d753e5c9a1e9cbb98be41145a9d288d6d719adcc
7
- data.tar.gz: 95a8d13b133a0256ffb71df70e4348845dbcbe0c848a94feb0ceaf205e274f918d84529ef7d0773884e51f2e504625a96a4fdf548b17f03fa408c39f763609b6
6
+ metadata.gz: 6d403109b1bbf55e1b0ab799d8c74752677784ca0c12cb5b1e21f62c9bdd244245966db8020b20a8d4ed988263a9535aef5a8aff24b50587c9583a67109d7677
7
+ data.tar.gz: 205d6c9859ec8d12ddf7630cbd3893a13d3efb3537dd734e53f17efe31d52399488761da45684d0da7e5074ce950c47a7e51f4a1446577e36f7c3c7838604a7a
@@ -1,3 +1,10 @@
1
+ ## 0.43.10 2020-07-23
2
+
3
+ * Fix race condition when terminating fibers (#33)
4
+ * Fix lock release in `Mutex` (#32)
5
+ * Virtualize agent interface
6
+ * Implement `LibevAgent_connect`
7
+
1
8
  ## 0.43.9 2020-07-22
2
9
 
3
10
  * Rewrite `Channel` using `Queue`
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.43.9)
4
+ polyphony (0.43.10)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/TODO.md CHANGED
@@ -1,8 +1,4 @@
1
- - Implement `LibevAgent#connect` API
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 */
@@ -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 = LibevAgent_wait_event(agent, Qnil);
69
+ VALUE switchpoint_result = __AGENT__.wait_event(agent, Qnil);
70
70
  event->waiting_fiber = Qnil;
71
71
 
72
72
  TEST_RESUME_EXCEPTION(switchpoint_result);
@@ -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 LibevAgent_break(VALUE self) {
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
- // VALUE LibevAgent_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
698
- // struct LibevAgent_t *agent;
699
- // struct libev_io watcher;
700
- // rb_io_t *fptr;
701
- // struct sockaddr_in addr;
702
- // char *host_buf = StringValueCStr(host);
703
- // VALUE switchpoint_result = Qnil;
704
- // VALUE underlying_sock = rb_iv_get(sock, "@io");
705
- // if (underlying_sock != Qnil) sock = underlying_sock;
706
-
707
- // GetLibevAgent(self, agent);
708
- // GetOpenFile(sock, fptr);
709
- // io_set_nonblock(fptr, sock);
710
- // watcher.fiber = Qnil;
711
-
712
- // addr.sin_family = AF_INET;
713
- // addr.sin_addr.s_addr = inet_addr(host_buf);
714
- // addr.sin_port = htons(NUM2INT(port));
715
-
716
- // while (1) {
717
- // int result = connect(fptr->fd, &addr, sizeof(addr));
718
- // if (result < 0) {
719
- // int e = errno;
720
- // if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
721
-
722
- // switchpoint_result = libev_io_wait(agent, &watcher, fptr, EV_WRITE);
723
- // if (TEST_EXCEPTION(switchpoint_result)) goto error;
724
- // }
725
- // else {
726
- // switchpoint_result = libev_snooze();
727
- // if (TEST_EXCEPTION(switchpoint_result)) goto error;
728
-
729
- // return sock;
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
- cLibevAgent = rb_define_class_under(mPolyphony, "LibevAgent", rb_cData);
857
- rb_define_alloc_func(cLibevAgent, LibevAgent_allocate);
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(cLibevAgent, "initialize", LibevAgent_initialize, 0);
860
- rb_define_method(cLibevAgent, "finalize", LibevAgent_finalize, 0);
861
- rb_define_method(cLibevAgent, "post_fork", LibevAgent_post_fork, 0);
862
- rb_define_method(cLibevAgent, "pending_count", LibevAgent_pending_count, 0);
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(cLibevAgent, "ref", LibevAgent_ref, 0);
865
- rb_define_method(cLibevAgent, "unref", LibevAgent_unref, 0);
860
+ rb_define_method(cAgent, "ref", LibevAgent_ref, 0);
861
+ rb_define_method(cAgent, "unref", LibevAgent_unref, 0);
866
862
 
867
- rb_define_method(cLibevAgent, "poll", LibevAgent_poll, 3);
868
- rb_define_method(cLibevAgent, "break", LibevAgent_break, 0);
863
+ rb_define_method(cAgent, "poll", LibevAgent_poll, 3);
864
+ rb_define_method(cAgent, "break", LibevAgent_wakeup, 0);
869
865
 
870
- rb_define_method(cLibevAgent, "read", LibevAgent_read, 4);
871
- rb_define_method(cLibevAgent, "read_loop", LibevAgent_read_loop, 1);
872
- rb_define_method(cLibevAgent, "write", LibevAgent_write_m, -1);
873
- rb_define_method(cLibevAgent, "accept", LibevAgent_accept, 1);
874
- rb_define_method(cLibevAgent, "accept_loop", LibevAgent_accept_loop, 1);
875
- // rb_define_method(cLibevAgent, "connect", LibevAgent_accept, 3);
876
- rb_define_method(cLibevAgent, "wait_io", LibevAgent_wait_io, 2);
877
- rb_define_method(cLibevAgent, "sleep", LibevAgent_sleep, 1);
878
- rb_define_method(cLibevAgent, "waitpid", LibevAgent_waitpid, 1);
879
- rb_define_method(cLibevAgent, "wait_event", LibevAgent_wait_event, 1);
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
  }
@@ -21,6 +21,8 @@ ID ID_R;
21
21
  ID ID_W;
22
22
  ID ID_RW;
23
23
 
24
+ agent_interface_t agent_interface;
25
+
24
26
  VALUE Polyphony_snooze(VALUE self) {
25
27
  VALUE ret;
26
28
  VALUE fiber = rb_fiber_current();
@@ -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);
@@ -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 = LibevAgent_wait_event(agent, Qnil);
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);
@@ -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(LibevAgent_ref_count(agent));
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
- LibevAgent_reset_ref_count(agent);
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 = LibevAgent_pending_count(agent);
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
- FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
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
- // if fiber is already scheduled, just set the scheduled value, then return
58
- if (rb_ivar_get(fiber, ID_runnable) != Qnil) return self;
67
+ FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
59
68
 
60
- queue = rb_ivar_get(self, ID_run_queue);
61
- Queue_push(queue, fiber);
62
- rb_ivar_set(fiber, ID_runnable, Qtrue);
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
- if (rb_thread_current() != self) {
65
- // if the fiber scheduling is done across threads, we need to make sure the
66
- // target thread is woken up in case it is in the middle of running its
67
- // event selector. Otherwise it's gonna be stuck waiting for an event to
68
- // happen, not knowing that it there's already a fiber ready to run in its
69
- // run queue.
70
- VALUE agent = rb_ivar_get(self,ID_ivar_agent);
71
- LibevAgent_break(agent);
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
- LibevAgent_break(agent);
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 = LibevAgent_ref_count(agent);
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
- LibevAgent_poll(agent, Qtrue, current_fiber, queue);
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
- LibevAgent_poll(agent, Qnil, current_fiber, queue);
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 (LibevAgent_break(agent) == Qnil) {
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
  }
@@ -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::LibevAgent.new
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'
@@ -17,7 +17,7 @@ module Polyphony
17
17
  yield
18
18
  ensure
19
19
  @holding_fiber = nil
20
- @store << token
20
+ @store << token if token
21
21
  end
22
22
  end
23
23
  end
@@ -24,15 +24,7 @@ class ::Socket
24
24
  NO_EXCEPTION = { exception: false }.freeze
25
25
 
26
26
  def connect(remotesockaddr)
27
- loop do
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::LibevAgent.new
21
+ @agent = Polyphony::Agent.new
22
22
  setup
23
23
  @ready = true
24
24
  result = @block.(*@args)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.43.9'
4
+ VERSION = '0.43.10'
5
5
  end
@@ -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::LibevAgent.new
34
+ Thread.current.agent = Polyphony::Agent.new
35
35
  sleep 0 # apparently this helps with timer accuracy
36
36
  end
37
37
 
@@ -6,7 +6,7 @@ class AgentTest < MiniTest::Test
6
6
  def setup
7
7
  super
8
8
  @prev_agent = Thread.current.agent
9
- @agent = Polyphony::LibevAgent.new
9
+ @agent = Polyphony::Agent.new
10
10
  Thread.current.agent = @agent
11
11
  end
12
12
 
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.9
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-22 00:00:00.000000000 Z
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.1.2
480
+ rubygems_version: 3.0.8
480
481
  signing_key:
481
482
  specification_version: 4
482
483
  summary: Fine grained concurrency for Ruby