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 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