polyphony 0.34 → 0.36

Sign up to get free protection for your applications and to get access to all the features.
data/ext/gyro/queue.c CHANGED
@@ -29,12 +29,11 @@ static size_t Gyro_Queue_size(const void *ptr) {
29
29
  static const rb_data_type_t Gyro_Queue_type = {
30
30
  "Gyro_Queue",
31
31
  {Gyro_Queue_mark, Gyro_Queue_free, Gyro_Queue_size,},
32
- 0, 0,
33
- RUBY_TYPED_FREE_IMMEDIATELY,
32
+ 0, 0, 0
34
33
  };
35
34
 
36
35
  static VALUE Gyro_Queue_allocate(VALUE klass) {
37
- struct Gyro_Queue *queue = (struct Gyro_Queue *)xmalloc(sizeof(struct Gyro_Queue));
36
+ struct Gyro_Queue *queue = ALLOC(struct Gyro_Queue);
38
37
  return TypedData_Wrap_Struct(klass, &Gyro_Queue_type, queue);
39
38
  }
40
39
  #define GetGyro_Queue(obj, queue) \
@@ -56,7 +55,7 @@ VALUE Gyro_Queue_push(VALUE self, VALUE value) {
56
55
 
57
56
  if (RARRAY_LEN(queue->wait_queue) > 0) {
58
57
  VALUE async = rb_ary_shift(queue->wait_queue);
59
- rb_funcall(async, ID_signal_bang, 1, Qnil);
58
+ rb_funcall(async, ID_signal, 1, Qnil);
60
59
  }
61
60
 
62
61
  rb_ary_push(queue->queue, value);
@@ -68,13 +67,14 @@ VALUE Gyro_Queue_shift(VALUE self) {
68
67
  GetGyro_Queue(self, queue);
69
68
 
70
69
  if (RARRAY_LEN(queue->queue) == 0) {
71
- VALUE async = rb_funcall(cGyro_Async, ID_new, 0);
70
+ VALUE async = Fiber_auto_async(rb_fiber_current());
72
71
  rb_ary_push(queue->wait_queue, async);
73
72
  VALUE ret = Gyro_Async_await_no_raise(async);
74
73
  if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
75
74
  rb_ary_delete(queue->wait_queue, async);
76
75
  return rb_funcall(rb_mKernel, ID_raise, 1, ret);
77
76
  }
77
+ RB_GC_GUARD(ret);
78
78
  }
79
79
 
80
80
  return rb_ary_shift(queue->queue);
data/ext/gyro/selector.c CHANGED
@@ -5,19 +5,20 @@ struct Gyro_Selector {
5
5
  long run_no_wait_count;
6
6
  int ev_loop_running;
7
7
  struct ev_async async;
8
+ VALUE active_watchers;
8
9
  };
9
10
 
10
11
  VALUE cGyro_Selector = Qnil;
11
12
 
12
13
  static void Gyro_Selector_mark(void *ptr) {
13
- // struct Gyro_Selector *selector = ptr;
14
+ struct Gyro_Selector *selector = ptr;
15
+ rb_gc_mark(selector->active_watchers);
14
16
  }
15
17
 
16
18
  static void Gyro_Selector_free(void *ptr) {
17
19
  struct Gyro_Selector *selector = ptr;
18
20
  ev_async_stop(selector->ev_loop, &selector->async);
19
21
  if (selector->ev_loop && !ev_is_default_loop(selector->ev_loop)) {
20
- // printf("Selector garbage collected before being stopped!\n");
21
22
  ev_loop_destroy(selector->ev_loop);
22
23
  }
23
24
  xfree(selector);
@@ -30,12 +31,11 @@ static size_t Gyro_Selector_size(const void *ptr) {
30
31
  static const rb_data_type_t Gyro_Selector_type = {
31
32
  "Gyro_Selector",
32
33
  {Gyro_Selector_mark, Gyro_Selector_free, Gyro_Selector_size,},
33
- 0, 0,
34
- RUBY_TYPED_FREE_IMMEDIATELY,
34
+ 0, 0, 0
35
35
  };
36
36
 
37
37
  static VALUE Gyro_Selector_allocate(VALUE klass) {
38
- struct Gyro_Selector *selector = (struct Gyro_Selector *)xmalloc(sizeof(struct Gyro_Selector));
38
+ struct Gyro_Selector *selector = ALLOC(struct Gyro_Selector);
39
39
  return TypedData_Wrap_Struct(klass, &Gyro_Selector_type, selector);
40
40
  }
41
41
 
@@ -75,6 +75,12 @@ void dummy_async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, in
75
75
  // up the event loop.
76
76
  }
77
77
 
78
+ inline void Gyro_Selector_run_ev_loop(struct Gyro_Selector *selector, int flags) {
79
+ selector->ev_loop_running = 1;
80
+ ev_run(selector->ev_loop, flags);
81
+ selector->ev_loop_running = 0;
82
+ }
83
+
78
84
  static VALUE Gyro_Selector_initialize(VALUE self, VALUE thread) {
79
85
  struct Gyro_Selector *selector;
80
86
  GetGyro_Selector(self, selector);
@@ -83,21 +89,35 @@ static VALUE Gyro_Selector_initialize(VALUE self, VALUE thread) {
83
89
  selector->ev_loop = use_default_loop ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
84
90
  selector->run_no_wait_count = 0;
85
91
 
92
+ selector->active_watchers = rb_hash_new();
93
+
86
94
  ev_async_init(&selector->async, dummy_async_callback);
87
95
  ev_async_start(selector->ev_loop, &selector->async);
88
- ev_run(selector->ev_loop, EVRUN_NOWAIT);
96
+ Gyro_Selector_run_ev_loop(selector, EVRUN_NOWAIT);
89
97
  return Qnil;
90
98
  }
91
99
 
100
+ inline void Gyro_Selector_add_active_watcher(VALUE self, VALUE watcher) {
101
+ struct Gyro_Selector *selector;
102
+ GetGyro_Selector(self, selector);
103
+
104
+ rb_hash_aset(selector->active_watchers, watcher, Qtrue);
105
+ }
106
+
107
+ inline void Gyro_Selector_remove_active_watcher(VALUE self, VALUE watcher) {
108
+ struct Gyro_Selector *selector;
109
+ GetGyro_Selector(self, selector);
110
+
111
+ rb_hash_delete(selector->active_watchers, watcher);
112
+ }
113
+
92
114
  inline VALUE Gyro_Selector_run(VALUE self, VALUE current_fiber) {
93
115
  struct Gyro_Selector *selector;
94
116
  GetGyro_Selector(self, selector);
95
117
  if (selector->ev_loop) {
96
118
  selector->run_no_wait_count = 0;
97
119
  FIBER_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
98
- selector->ev_loop_running = 1;
99
- ev_run(selector->ev_loop, EVRUN_ONCE);
100
- selector->ev_loop_running = 0;
120
+ Gyro_Selector_run_ev_loop(selector, EVRUN_ONCE);
101
121
  FIBER_TRACE(2, SYM_fiber_ev_loop_leave, current_fiber);
102
122
  }
103
123
  return Qnil;
@@ -114,7 +134,7 @@ inline void Gyro_Selector_run_no_wait(VALUE self, VALUE current_fiber, long runn
114
134
 
115
135
  selector->run_no_wait_count = 0;
116
136
  FIBER_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
117
- ev_run(selector->ev_loop, EVRUN_NOWAIT);
137
+ Gyro_Selector_run_ev_loop(selector, EVRUN_NOWAIT);
118
138
  FIBER_TRACE(2, SYM_fiber_ev_loop_leave, current_fiber);
119
139
  }
120
140
 
@@ -166,7 +186,9 @@ inline static VALUE Gyro_Selector_wait_writable(VALUE self, VALUE io) {
166
186
 
167
187
  inline static VALUE Gyro_Selector_wait_timeout(VALUE self, VALUE duration) {
168
188
  VALUE watcher = rb_funcall(cGyro_Timer, ID_new, 2, duration, Qnil);
169
- return Gyro_Timer_await(watcher);
189
+ VALUE ret = Gyro_Timer_await(watcher);
190
+ RB_GC_GUARD(watcher);
191
+ return ret;
170
192
  }
171
193
 
172
194
  void Init_Gyro_Selector() {
data/ext/gyro/signal.c CHANGED
@@ -5,7 +5,9 @@ struct Gyro_Signal {
5
5
  struct ev_loop *ev_loop;
6
6
  int active;
7
7
  int signum;
8
+ VALUE self;
8
9
  VALUE fiber;
10
+ VALUE selector;
9
11
  };
10
12
 
11
13
  static VALUE cGyro_Signal = Qnil;
@@ -15,13 +17,16 @@ static void Gyro_Signal_mark(void *ptr) {
15
17
  if (signal->fiber != Qnil) {
16
18
  rb_gc_mark(signal->fiber);
17
19
  }
20
+ if (signal->selector != Qnil) {
21
+ rb_gc_mark(signal->selector);
22
+ }
18
23
  }
19
24
 
20
25
  static void Gyro_Signal_free(void *ptr) {
21
26
  struct Gyro_Signal *signal = ptr;
22
27
  if (signal->active) {
23
- printf("Signal watcher garbage collected while still active!\n");
24
- // ev_signal_stop(signal->ev_loop, &signal->ev_signal);
28
+ ev_clear_pending(signal->ev_loop, &signal->ev_signal);
29
+ ev_signal_stop(signal->ev_loop, &signal->ev_signal);
25
30
  }
26
31
  xfree(signal);
27
32
  }
@@ -33,26 +38,41 @@ static size_t Gyro_Signal_size(const void *ptr) {
33
38
  static const rb_data_type_t Gyro_Signal_type = {
34
39
  "Gyro_Signal",
35
40
  {Gyro_Signal_mark, Gyro_Signal_free, Gyro_Signal_size,},
36
- 0, 0,
37
- RUBY_TYPED_FREE_IMMEDIATELY,
41
+ 0, 0, 0
38
42
  };
39
43
 
40
44
  static VALUE Gyro_Signal_allocate(VALUE klass) {
41
- struct Gyro_Signal *signal = (struct Gyro_Signal *)xmalloc(sizeof(struct Gyro_Signal));
45
+ struct Gyro_Signal *signal = ALLOC(struct Gyro_Signal);
42
46
  return TypedData_Wrap_Struct(klass, &Gyro_Signal_type, signal);
43
47
  }
44
48
 
49
+ inline void Gyro_Signal_activate(struct Gyro_Signal *signal) {
50
+ if (signal->active) return;
51
+
52
+ signal->active = 1;
53
+ signal->fiber = rb_fiber_current();
54
+ signal->selector = Thread_current_event_selector();
55
+ signal->ev_loop = Gyro_Selector_ev_loop(signal->selector);
56
+ Gyro_Selector_add_active_watcher(signal->selector, signal->self);
57
+ ev_signal_start(signal->ev_loop, &signal->ev_signal);
58
+ }
59
+
60
+ inline void Gyro_Signal_deactivate(struct Gyro_Signal *signal) {
61
+ if (!signal->active) return;
62
+
63
+ ev_signal_stop(signal->ev_loop, &signal->ev_signal);
64
+ Gyro_Selector_remove_active_watcher(signal->selector, signal->self);
65
+ signal->active = 0;
66
+ signal->ev_loop = 0;
67
+ signal->selector = Qnil;
68
+ signal->fiber = Qnil;
69
+ }
70
+
45
71
  void Gyro_Signal_callback(struct ev_loop *ev_loop, struct ev_signal *ev_signal, int revents) {
46
72
  struct Gyro_Signal *signal = (struct Gyro_Signal*)ev_signal;
47
73
 
48
- if (signal->fiber != Qnil) {
49
- VALUE fiber = signal->fiber;
50
-
51
- ev_signal_stop(signal->ev_loop, ev_signal);
52
- signal->active = 0;
53
- signal->fiber = Qnil;
54
- Gyro_schedule_fiber(fiber, INT2NUM(signal->signum));
55
- }
74
+ Fiber_make_runnable(signal->fiber, INT2NUM(signal->signum));
75
+ Gyro_Signal_deactivate(signal);
56
76
  }
57
77
 
58
78
  #define GetGyro_Signal(obj, signal) \
@@ -63,7 +83,13 @@ static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
63
83
  VALUE signum = sig;
64
84
 
65
85
  GetGyro_Signal(self, signal);
86
+
87
+ signal->self = self;
88
+ signal->fiber = Qnil;
89
+ signal->selector = Qnil;
66
90
  signal->signum = NUM2INT(signum);
91
+ signal->active = 0;
92
+ signal->ev_loop = 0;
67
93
 
68
94
  ev_signal_init(&signal->ev_signal, Gyro_Signal_callback, signal->signum);
69
95
 
@@ -72,31 +98,15 @@ static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
72
98
 
73
99
  static VALUE Gyro_Signal_await(VALUE self) {
74
100
  struct Gyro_Signal *signal;
75
- VALUE ret;
76
-
77
101
  GetGyro_Signal(self, signal);
78
102
 
79
- signal->fiber = rb_fiber_current();
80
- signal->active = 1;
81
- signal->ev_loop = Gyro_Selector_current_thread_ev_loop();
82
- ev_signal_start(signal->ev_loop, &signal->ev_signal);
103
+ Gyro_Signal_activate(signal);
104
+ VALUE ret = Gyro_switchpoint();
105
+ Gyro_Signal_deactivate(signal);
83
106
 
84
- ret = Fiber_await();
107
+ TEST_RESUME_EXCEPTION(ret);
85
108
  RB_GC_GUARD(ret);
86
-
87
- if (signal->active) {
88
- signal->active = 0;
89
- signal->fiber = Qnil;
90
- ev_signal_stop(signal->ev_loop, &signal->ev_signal);
91
- }
92
-
93
- // fiber is resumed, check if resumed value is an exception
94
- signal->fiber = Qnil;
95
- if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
96
- return rb_funcall(rb_mKernel, ID_raise, 1, ret);
97
- }
98
- else
99
- return ret;
109
+ return ret;
100
110
  }
101
111
 
102
112
  void Init_Gyro_Signal() {
data/ext/gyro/socket.c CHANGED
@@ -94,9 +94,8 @@ static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE sock) {
94
94
  arg.fd = fptr->fd;
95
95
  arg.flags = NUM2INT(flags);
96
96
  while ((n = (ssize_t)func(&arg)) < 0) {
97
- if (write_watcher == Qnil) {
98
- write_watcher = IO_write_watcher(sock);
99
- }
97
+ if (NIL_P(write_watcher))
98
+ write_watcher = Gyro_IO_auto_io(fptr->fd, EV_WRITE);
100
99
  Gyro_IO_await(write_watcher);
101
100
  }
102
101
  return SSIZET2NUM(n);
@@ -132,8 +131,8 @@ static VALUE BasicSocket_recv(int argc, VALUE *argv, VALUE sock) {
132
131
  if (n < 0) {
133
132
  int e = errno;
134
133
  if (e == EWOULDBLOCK || e == EAGAIN) {
135
- if (read_watcher == Qnil)
136
- read_watcher = IO_read_watcher(sock);
134
+ if (NIL_P(read_watcher))
135
+ read_watcher = Gyro_IO_auto_io(fptr->fd, EV_READ);
137
136
  Gyro_IO_await(read_watcher);
138
137
  }
139
138
  else
@@ -169,8 +168,8 @@ static VALUE Socket_accept(VALUE sock) {
169
168
  if (fd < 0) {
170
169
  int e = errno;
171
170
  if (e == EWOULDBLOCK || e == EAGAIN) {
172
- if (read_watcher == Qnil)
173
- read_watcher = IO_read_watcher(sock);
171
+ if (NIL_P(read_watcher))
172
+ read_watcher = Gyro_IO_auto_io(fptr->fd, EV_READ);
174
173
  Gyro_IO_await(read_watcher);
175
174
  }
176
175
  else
data/ext/gyro/thread.c CHANGED
@@ -227,7 +227,7 @@ VALUE Thread_post_fork(VALUE self) {
227
227
  return self;
228
228
  }
229
229
 
230
- VALUE Fiber_await() {
230
+ VALUE Gyro_switchpoint() {
231
231
  VALUE thread = rb_thread_current();
232
232
  Thread_ref(thread);
233
233
  VALUE ret = Thread_switch_fiber(thread);
data/ext/gyro/timer.c CHANGED
@@ -6,7 +6,6 @@ struct Gyro_Timer {
6
6
  int active;
7
7
  double after;
8
8
  double repeat;
9
- int should_free;
10
9
  VALUE self;
11
10
  VALUE fiber;
12
11
  VALUE selector;
@@ -27,11 +26,10 @@ static void Gyro_Timer_mark(void *ptr) {
27
26
  static void Gyro_Timer_free(void *ptr) {
28
27
  struct Gyro_Timer *timer = ptr;
29
28
  if (timer->active) {
30
- printf("Timer watcher garbage collected while still active (%g, %g)!\n", timer->after, timer->repeat);
31
- timer->should_free = 1;
32
- } else {
33
- xfree(timer);
29
+ ev_clear_pending(timer->ev_loop, &timer->ev_timer);
30
+ ev_timer_stop(timer->ev_loop, &timer->ev_timer);
34
31
  }
32
+ xfree(timer);
35
33
  }
36
34
 
37
35
  static size_t Gyro_Timer_size(const void *ptr) {
@@ -41,34 +39,50 @@ static size_t Gyro_Timer_size(const void *ptr) {
41
39
  static const rb_data_type_t Gyro_Timer_type = {
42
40
  "Gyro_Timer",
43
41
  {Gyro_Timer_mark, Gyro_Timer_free, Gyro_Timer_size,},
44
- 0, 0,
45
- RUBY_TYPED_FREE_IMMEDIATELY,
42
+ 0, 0, 0
46
43
  };
47
44
 
48
45
  static VALUE Gyro_Timer_allocate(VALUE klass) {
49
- struct Gyro_Timer *timer = (struct Gyro_Timer *)xmalloc(sizeof(struct Gyro_Timer));
46
+ struct Gyro_Timer *timer = ALLOC(struct Gyro_Timer);
50
47
  return TypedData_Wrap_Struct(klass, &Gyro_Timer_type, timer);
51
48
  }
49
+
52
50
  #define GetGyro_Timer(obj, timer) \
53
51
  TypedData_Get_Struct((obj), struct Gyro_Timer, &Gyro_Timer_type, (timer))
54
52
 
55
- void Gyro_Timer_callback(struct ev_loop *ev_loop, struct ev_timer *ev_timer, int revents) {
56
- struct Gyro_Timer *timer = (struct Gyro_Timer*)ev_timer;
53
+ inline void Gyro_Timer_activate(struct Gyro_Timer *timer) {
54
+ timer->fiber = rb_fiber_current();
55
+ timer->selector = Thread_current_event_selector();
56
+ timer->ev_loop = Gyro_Selector_ev_loop(timer->selector);
57
57
 
58
- if (timer->should_free) {
59
- ev_timer_stop(timer->ev_loop, ev_timer);
60
- xfree(timer);
61
- return;
62
- }
58
+ if (timer->active) return;
59
+
60
+ timer->active = 1;
61
+ Gyro_Selector_add_active_watcher(timer->selector, timer->self);
62
+ ev_timer_start(timer->ev_loop, &timer->ev_timer);
63
+ }
64
+
65
+ inline void Gyro_Timer_deactivate(struct Gyro_Timer *timer, int non_recurring_only) {
66
+ if (!timer->active) return;
63
67
 
64
- if (!timer->repeat) {
68
+ if (!timer->repeat || !non_recurring_only) {
69
+ ev_timer_stop(timer->ev_loop, &timer->ev_timer);
70
+ if (RTEST(timer->selector)) {
71
+ Gyro_Selector_remove_active_watcher(timer->selector, timer->self);
72
+ timer->selector = Qnil;
73
+ }
74
+ timer->ev_loop = 0;
65
75
  timer->active = 0;
66
- timer->selector = Qnil;
67
76
  }
68
77
 
69
- if (timer->fiber != Qnil) {
70
- Gyro_schedule_fiber(timer->fiber, DBL2NUM(timer->after));
71
- }
78
+ timer->fiber = Qnil;
79
+ }
80
+
81
+ void Gyro_Timer_callback(struct ev_loop *ev_loop, struct ev_timer *ev_timer, int revents) {
82
+ struct Gyro_Timer *timer = (struct Gyro_Timer*)ev_timer;
83
+
84
+ Fiber_make_runnable(timer->fiber, DBL2NUM(timer->after));
85
+ Gyro_Timer_deactivate(timer, 1);
72
86
  }
73
87
 
74
88
  static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat) {
@@ -78,15 +92,13 @@ static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat) {
78
92
 
79
93
  timer->self = self;
80
94
  timer->fiber = Qnil;
95
+ timer->selector = Qnil;
81
96
  timer->after = NUM2DBL(after);
82
97
  timer->repeat = NUM2DBL(repeat);
83
98
  timer->active = 0;
84
-
85
- timer->should_free = 0;
99
+ timer->ev_loop = 0;
86
100
 
87
101
  ev_timer_init(&timer->ev_timer, Gyro_Timer_callback, timer->after, timer->repeat);
88
- timer->ev_loop = 0;
89
- timer->selector = Qnil;
90
102
 
91
103
  return Qnil;
92
104
  }
@@ -95,53 +107,21 @@ VALUE Gyro_Timer_stop(VALUE self) {
95
107
  struct Gyro_Timer *timer;
96
108
  GetGyro_Timer(self, timer);
97
109
 
98
- if (timer->active) {
99
- timer->active = 0;
100
- timer->fiber = Qnil;
101
- timer->selector = Qnil;
102
- ev_timer_stop(timer->ev_loop, &timer->ev_timer);
103
- timer->ev_loop = 0;
104
- }
105
-
110
+ Gyro_Timer_deactivate(timer, 0);
106
111
  return self;
107
112
  }
108
113
 
109
114
  VALUE Gyro_Timer_await(VALUE self) {
110
115
  struct Gyro_Timer *timer;
111
- VALUE ret;
112
-
113
116
  GetGyro_Timer(self, timer);
114
117
 
115
- timer->fiber = rb_fiber_current();
116
- timer->selector = Thread_current_event_selector();
117
- timer->ev_loop = Gyro_Selector_ev_loop(timer->selector);
118
-
119
- if (timer->active != 1) {
120
- timer->active = 1;
121
- ev_timer_start(timer->ev_loop, &timer->ev_timer);
122
- }
118
+ Gyro_Timer_activate(timer);
119
+ VALUE ret = Gyro_switchpoint();
120
+ Gyro_Timer_deactivate(timer, 1);
123
121
 
124
- ret = Fiber_await();
122
+ TEST_RESUME_EXCEPTION(ret);
125
123
  RB_GC_GUARD(ret);
126
-
127
- if (timer->active && (timer->repeat == .0)) {
128
- timer->active = 0;
129
- timer->fiber = Qnil;
130
- timer->selector = Qnil;
131
- ev_timer_stop(timer->ev_loop, &timer->ev_timer);
132
- timer->ev_loop = 0;
133
- }
134
-
135
- // fiber is resumed, check if resumed value is an exception
136
- timer->fiber = Qnil;
137
- timer->selector = Qnil;
138
-
139
- RB_GC_GUARD(self);
140
- if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
141
- return rb_funcall(rb_mKernel, ID_raise, 1, ret);
142
- }
143
- else
144
- return ret;
124
+ return ret;
145
125
  }
146
126
 
147
127
  void Init_Gyro_Timer() {