event 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,7 +22,7 @@
22
22
 
23
23
  #include <ruby.h>
24
24
 
25
- #define EVENT_BACKEND_URING
25
+ #define EVENT_SELECTOR_URING
26
26
 
27
- void Init_Event_Backend_URing(VALUE Event_Backend);
28
- VALUE Event_Backend_URing_select(VALUE self, VALUE duration);
27
+ void Init_Event_Selector_URing(VALUE Event_Selector);
28
+ VALUE Event_Selector_URing_select(VALUE self, VALUE duration);
data/lib/event.rb CHANGED
@@ -19,7 +19,8 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  require_relative 'event/version'
22
- require_relative 'event/backend'
22
+ require_relative 'event/selector'
23
+ require_relative 'event/selector'
23
24
 
24
25
  module Event
25
26
  # These constants are the same as those defined in IO.
@@ -0,0 +1,126 @@
1
+ # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require "event/version"
22
+
23
+ module Event
24
+ class Debug
25
+ def initialize(selector)
26
+ @selector = selector
27
+
28
+ @readable = {}
29
+ @writable = {}
30
+ @priority = {}
31
+ end
32
+
33
+ def close
34
+ if @selector.nil?
35
+ raise "Selector already closed!"
36
+ end
37
+
38
+ @selector.close
39
+ @selector = nil
40
+ end
41
+
42
+ def transfer(fiber, *arguments)
43
+ @selector.transfer(fiber, *arguments)
44
+ end
45
+
46
+ def yield
47
+ @selector.yield
48
+ end
49
+
50
+ def push(fiber)
51
+ @selector.push(fiber)
52
+ end
53
+
54
+ def raise(fiber, *arguments)
55
+ @selector.raise(fiber, *arguments)
56
+ end
57
+
58
+ def ready?
59
+ @selector.ready?
60
+ end
61
+
62
+ def io_wait(fiber, io, events)
63
+ register_readable(fiber, io, events)
64
+ end
65
+
66
+ def select(duration = nil)
67
+ @selector.select(duration)
68
+ end
69
+
70
+ private
71
+
72
+ def register_readable(fiber, io, events)
73
+ if (events & READABLE) > 0
74
+ if @readable.key?(io)
75
+ raise "Cannot wait for #{io} to become readable from multiple fibers."
76
+ end
77
+
78
+ begin
79
+ @readable[io] = fiber
80
+
81
+ register_writable(fiber, io, events)
82
+ ensure
83
+ @readable.delete(io)
84
+ end
85
+ else
86
+ register_writable(fiber, io, events)
87
+ end
88
+ end
89
+
90
+ def register_writable(fiber, io, events)
91
+ if (events & WRITABLE) > 0
92
+ if @writable.key?(io)
93
+ raise "Cannot wait for #{io} to become writable from multiple fibers."
94
+ end
95
+
96
+ begin
97
+ @writable[io] = fiber
98
+
99
+ register_priority(fiber, io, events)
100
+ ensure
101
+ @writable.delete(io)
102
+ end
103
+ else
104
+ register_priority(fiber, io, events)
105
+ end
106
+ end
107
+
108
+ def register_priority(fiber, io, events)
109
+ if (events & PRIORITY) > 0
110
+ if @priority.key?(io)
111
+ raise "Cannot wait for #{io} to become priority from multiple fibers."
112
+ end
113
+
114
+ begin
115
+ @priority[io] = fiber
116
+
117
+ @selector.io_wait(fiber, io, events)
118
+ ensure
119
+ @priority.delete(io)
120
+ end
121
+ else
122
+ @selector.io_wait(fiber, io, events)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -18,9 +18,32 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require "event/version"
21
+ require_relative 'selector/select'
22
22
 
23
23
  module Event
24
- class Selector
24
+ module Selector
25
+ def self.default(env = ENV)
26
+ if name = env['EVENT_SELECTOR']&.to_sym
27
+ if Event::Selector.const_defined?(name)
28
+ return Event::Selector.const_get(name)
29
+ else
30
+ warn "Could not find EVENT_SELECTOR=#{name}!"
31
+ end
32
+ end
33
+
34
+ if self.const_defined?(:URing)
35
+ return Event::Selector::URing
36
+ elsif self.const_defined?(:KQueue)
37
+ return Event::Selector::KQueue
38
+ elsif self.const_defined?(:EPoll)
39
+ return Event::Selector::EPoll
40
+ else
41
+ return Event::Selector::Select
42
+ end
43
+ end
44
+
45
+ def self.new(...)
46
+ default.new(...)
47
+ end
25
48
  end
26
49
  end
@@ -19,7 +19,7 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Event
22
- module Backend
22
+ module Selector
23
23
  class Select
24
24
  def initialize(loop)
25
25
  @loop = loop
@@ -36,18 +36,30 @@ module Event
36
36
  @writable = nil
37
37
  end
38
38
 
39
- def defer
39
+ def transfer(fiber, *arguments)
40
+ @ready.push(Fiber.current)
41
+ fiber.transfer(*arguments)
42
+ ensure
43
+ @ready.delete(fiber)
44
+ end
45
+
46
+ def yield
40
47
  fiber = Fiber.current
41
48
  @ready.push(fiber)
42
49
  @loop.transfer
43
50
  ensure
44
- # Linear scan :(
45
51
  @ready.delete(fiber)
46
52
  end
47
53
 
48
- def transfer(fiber)
54
+ def push(fiber)
55
+ @ready.push(fiber)
56
+ end
57
+
58
+ def raise(fiber, *arguments)
49
59
  @ready.push(Fiber.current)
50
- fiber.transfer
60
+ @fiber.raise(*arguments)
61
+ ensure
62
+ @ready.delete(fiber)
51
63
  end
52
64
 
53
65
  def ready?
@@ -139,8 +151,13 @@ module Event
139
151
  end
140
152
 
141
153
  def select(duration = nil)
142
- while @ready.any?
143
- @ready.pop.transfer
154
+ if @ready.any?
155
+ ready = @ready
156
+ @ready = Array.new
157
+
158
+ ready.each do |fiber|
159
+ fiber.transfer if fiber.alive?
160
+ end
144
161
  end
145
162
 
146
163
  readable, writable, _ = ::IO.select(@readable.keys, @writable.keys, nil, duration)
data/lib/event/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Event
2
- VERSION = "0.7.0"
2
+ VERSION = "0.8.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: event
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-13 00:00:00.000000000 Z
11
+ date: 2021-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bake
@@ -74,16 +74,6 @@ extensions:
74
74
  extra_rdoc_files: []
75
75
  files:
76
76
  - ext/event/Makefile
77
- - ext/event/backend.o
78
- - ext/event/backend/backend.c
79
- - ext/event/backend/backend.h
80
- - ext/event/backend/epoll.c
81
- - ext/event/backend/epoll.h
82
- - ext/event/backend/kqueue.c
83
- - ext/event/backend/kqueue.h
84
- - ext/event/backend/pidfd.c
85
- - ext/event/backend/uring.c
86
- - ext/event/backend/uring.h
87
77
  - ext/event/event.bundle
88
78
  - ext/event/event.c
89
79
  - ext/event/event.h
@@ -92,11 +82,20 @@ files:
92
82
  - ext/event/extconf.rb
93
83
  - ext/event/kqueue.o
94
84
  - ext/event/mkmf.log
85
+ - ext/event/selector.o
86
+ - ext/event/selector/epoll.c
87
+ - ext/event/selector/epoll.h
88
+ - ext/event/selector/kqueue.c
89
+ - ext/event/selector/kqueue.h
90
+ - ext/event/selector/pidfd.c
91
+ - ext/event/selector/selector.c
92
+ - ext/event/selector/selector.h
93
+ - ext/event/selector/uring.c
94
+ - ext/event/selector/uring.h
95
95
  - lib/event.rb
96
- - lib/event/backend.rb
97
- - lib/event/backend/select.rb
98
- - lib/event/debug/selector.rb
96
+ - lib/event/debug.rb
99
97
  - lib/event/selector.rb
98
+ - lib/event/selector/select.rb
100
99
  - lib/event/version.rb
101
100
  homepage: https://github.com/socketry/event
102
101
  licenses:
data/ext/event/backend.o DELETED
Binary file
@@ -1,178 +0,0 @@
1
- // Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- //
3
- // Permission is hereby granted, free of charge, to any person obtaining a copy
4
- // of this software and associated documentation files (the "Software"), to deal
5
- // in the Software without restriction, including without limitation the rights
6
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- // copies of the Software, and to permit persons to whom the Software is
8
- // furnished to do so, subject to the following conditions:
9
- //
10
- // The above copyright notice and this permission notice shall be included in
11
- // all copies or substantial portions of the Software.
12
- //
13
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- // THE SOFTWARE.
20
-
21
- #include "backend.h"
22
- #include <fcntl.h>
23
-
24
- #ifndef HAVE__RB_FIBER_TRANSFER
25
- static ID id_transfer;
26
-
27
- VALUE
28
- Event_Backend_fiber_transfer(VALUE fiber) {
29
- return rb_funcall(fiber, id_transfer, 0);
30
- }
31
-
32
- VALUE
33
- Event_Backend_fiber_transfer_result(VALUE fiber, VALUE result) {
34
- return rb_funcall(fiber, id_transfer, 1, result);
35
- }
36
- #endif
37
-
38
- #ifndef HAVE_RB_IO_DESCRIPTOR
39
- static ID id_fileno;
40
-
41
- int Event_Backend_io_descriptor(VALUE io) {
42
- return RB_NUM2INT(rb_funcall(io, id_fileno, 0));
43
- }
44
- #endif
45
-
46
- #ifndef HAVE_RB_PROCESS_STATUS_WAIT
47
- static ID id_wait;
48
- static VALUE rb_Process_Status = Qnil;
49
-
50
- VALUE Event_Backend_process_status_wait(rb_pid_t pid)
51
- {
52
- return rb_funcall(rb_Process_Status, id_wait, 2, PIDT2NUM(pid), INT2NUM(WNOHANG));
53
- }
54
- #endif
55
-
56
- int Event_Backend_nonblock_set(int file_descriptor)
57
- {
58
- int flags = fcntl(file_descriptor, F_GETFL, 0);
59
-
60
- if (!(flags & O_NONBLOCK)) {
61
- fcntl(file_descriptor, F_SETFL, flags | O_NONBLOCK);
62
- }
63
-
64
- return flags;
65
- }
66
-
67
- void Event_Backend_nonblock_restore(int file_descriptor, int flags)
68
- {
69
- if (!(flags & O_NONBLOCK)) {
70
- fcntl(file_descriptor, F_SETFL, flags & ~flags);
71
- }
72
- }
73
-
74
- void Init_Event_Backend(VALUE Event_Backend) {
75
- #ifndef HAVE_RB_IO_DESCRIPTOR
76
- id_fileno = rb_intern("fileno");
77
- #endif
78
-
79
- #ifndef HAVE__RB_FIBER_TRANSFER
80
- id_transfer = rb_intern("transfer");
81
- #endif
82
-
83
- #ifndef HAVE_RB_PROCESS_STATUS_WAIT
84
- id_wait = rb_intern("wait");
85
- rb_Process_Status = rb_const_get_at(rb_mProcess, rb_intern("Status"));
86
- #endif
87
- }
88
-
89
- struct wait_and_transfer_arguments {
90
- struct Event_Backend *backend;
91
- struct Event_Backend_Queue *waiting;
92
- };
93
-
94
- static void queue_pop(struct Event_Backend *backend, struct Event_Backend_Queue *waiting) {
95
- if (waiting->behind) {
96
- waiting->behind->infront = waiting->infront;
97
- } else {
98
- backend->waiting = waiting->infront;
99
- }
100
-
101
- if (waiting->infront) {
102
- waiting->infront->behind = waiting->behind;
103
- } else {
104
- backend->ready = waiting->behind;
105
- }
106
- }
107
-
108
- static void queue_push(struct Event_Backend *backend, struct Event_Backend_Queue *waiting) {
109
- if (backend->waiting) {
110
- backend->waiting->behind = waiting;
111
- waiting->infront = backend->waiting;
112
- } else {
113
- backend->ready = waiting;
114
- }
115
-
116
- backend->waiting = waiting;
117
- }
118
-
119
- static VALUE wait_and_transfer(VALUE fiber) {
120
- return Event_Backend_fiber_transfer(fiber);
121
- }
122
-
123
- static VALUE wait_and_transfer_ensure(VALUE _arguments) {
124
- struct wait_and_transfer_arguments *arguments = (struct wait_and_transfer_arguments *)_arguments;
125
-
126
- queue_pop(arguments->backend, arguments->waiting);
127
-
128
- return Qnil;
129
- }
130
-
131
- void Event_Backend_wait_and_transfer(struct Event_Backend *backend, VALUE fiber)
132
- {
133
- struct Event_Backend_Queue waiting = {
134
- .behind = NULL,
135
- .infront = NULL,
136
- .fiber = rb_fiber_current()
137
- };
138
-
139
- queue_push(backend, &waiting);
140
-
141
- struct wait_and_transfer_arguments arguments = {
142
- .backend = backend,
143
- .waiting = &waiting,
144
- };
145
-
146
- rb_ensure(wait_and_transfer, fiber, wait_and_transfer_ensure, (VALUE)&arguments);
147
- }
148
-
149
- void Event_Backend_ready_pop(struct Event_Backend *backend)
150
- {
151
- // Get the current tail and head of the queue:
152
- struct Event_Backend_Queue *waiting = backend->waiting;
153
-
154
- // Process from head to tail in order:
155
- // During this, more items may be appended to tail.
156
- while (backend->ready) {
157
- struct Event_Backend_Queue *ready = backend->ready;
158
-
159
- Event_Backend_fiber_transfer(ready->fiber);
160
-
161
- if (ready == waiting) break;
162
- }
163
- }
164
-
165
- void Event_Backend_elapsed_time(struct timespec* start, struct timespec* stop, struct timespec *duration)
166
- {
167
- if ((stop->tv_nsec - start->tv_nsec) < 0) {
168
- duration->tv_sec = stop->tv_sec - start->tv_sec - 1;
169
- duration->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
170
- } else {
171
- duration->tv_sec = stop->tv_sec - start->tv_sec;
172
- duration->tv_nsec = stop->tv_nsec - start->tv_nsec;
173
- }
174
- }
175
-
176
- void Event_Backend_current_time(struct timespec *time) {
177
- clock_gettime(CLOCK_MONOTONIC, time);
178
- }