polyphony 0.13 → 0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.gitbook.yaml +5 -0
  3. data/.gitignore +55 -0
  4. data/.rubocop.yml +49 -0
  5. data/CHANGELOG.md +13 -2
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +31 -0
  8. data/LICENSE +21 -0
  9. data/README.md +35 -18
  10. data/Rakefile +20 -0
  11. data/TODO.md +49 -0
  12. data/docs/getting-started/getting-started.md +10 -0
  13. data/docs/getting-started/tutorial.md +2 -0
  14. data/docs/summary.md +9 -0
  15. data/examples/core/cancel.rb +10 -0
  16. data/examples/core/channel_echo.rb +43 -0
  17. data/examples/core/enumerator.rb +14 -0
  18. data/examples/core/fork.rb +22 -0
  19. data/examples/core/genserver.rb +74 -0
  20. data/examples/core/lock.rb +20 -0
  21. data/examples/core/move_on.rb +11 -0
  22. data/examples/core/move_on_twice.rb +17 -0
  23. data/examples/core/move_on_with_ensure.rb +17 -0
  24. data/examples/core/multiple_async.rb +17 -0
  25. data/examples/core/nested_async.rb +18 -0
  26. data/examples/core/nested_cancel.rb +41 -0
  27. data/examples/core/nested_multiple_async.rb +19 -0
  28. data/examples/core/next_tick.rb +13 -0
  29. data/examples/core/pulse.rb +13 -0
  30. data/examples/core/resource.rb +29 -0
  31. data/examples/core/resource_cancel.rb +34 -0
  32. data/examples/core/resource_delegate.rb +32 -0
  33. data/examples/core/sleep.rb +9 -0
  34. data/examples/core/sleep2.rb +13 -0
  35. data/examples/core/spawn.rb +15 -0
  36. data/examples/core/spawn_cancel.rb +19 -0
  37. data/examples/core/spawn_error.rb +28 -0
  38. data/examples/core/supervisor.rb +22 -0
  39. data/examples/core/supervisor_with_cancel_scope.rb +24 -0
  40. data/examples/core/supervisor_with_error.rb +23 -0
  41. data/examples/core/supervisor_with_manual_move_on.rb +25 -0
  42. data/examples/core/thread.rb +30 -0
  43. data/examples/core/thread_cancel.rb +30 -0
  44. data/examples/core/thread_pool.rb +60 -0
  45. data/examples/core/throttle.rb +17 -0
  46. data/examples/fs/read.rb +37 -0
  47. data/examples/interfaces/pg_client.rb +38 -0
  48. data/examples/interfaces/pg_pool.rb +37 -0
  49. data/examples/interfaces/pg_query.rb +32 -0
  50. data/examples/interfaces/redis_channels.rb +119 -0
  51. data/examples/interfaces/redis_client.rb +21 -0
  52. data/examples/interfaces/redis_pubsub.rb +26 -0
  53. data/examples/interfaces/redis_pubsub_perf.rb +65 -0
  54. data/examples/io/config.ru +3 -0
  55. data/examples/io/echo_client.rb +22 -0
  56. data/examples/io/echo_server.rb +14 -0
  57. data/examples/io/echo_server_with_timeout.rb +33 -0
  58. data/examples/io/echo_stdin.rb +15 -0
  59. data/examples/io/happy_eyeballs.rb +32 -0
  60. data/examples/io/http_client.rb +19 -0
  61. data/examples/io/http_server.js +24 -0
  62. data/examples/io/http_server.rb +16 -0
  63. data/examples/io/http_server_forked.rb +27 -0
  64. data/examples/io/http_server_throttled.rb +16 -0
  65. data/examples/io/http_ws_server.rb +42 -0
  66. data/examples/io/https_client.rb +17 -0
  67. data/examples/io/https_server.rb +23 -0
  68. data/examples/io/https_wss_server.rb +46 -0
  69. data/examples/io/rack_server.rb +19 -0
  70. data/examples/io/rack_server_https.rb +24 -0
  71. data/examples/io/rack_server_https_forked.rb +32 -0
  72. data/examples/io/websocket_server.rb +33 -0
  73. data/examples/io/ws_page.html +34 -0
  74. data/examples/io/wss_page.html +34 -0
  75. data/examples/performance/perf_multi_snooze.rb +21 -0
  76. data/examples/performance/perf_snooze.rb +30 -0
  77. data/examples/performance/thread-vs-fiber/polyphony_server.rb +63 -0
  78. data/examples/performance/thread-vs-fiber/threaded_server.rb +27 -0
  79. data/examples/streams/lines.rb +27 -0
  80. data/examples/streams/stdio.rb +18 -0
  81. data/ext/ev/async.c +168 -0
  82. data/ext/ev/child.c +169 -0
  83. data/ext/ev/ev.h +32 -0
  84. data/ext/ev/ev_ext.c +20 -0
  85. data/ext/ev/ev_module.c +222 -0
  86. data/ext/ev/io.c +405 -0
  87. data/ext/ev/libev.h +9 -0
  88. data/ext/ev/signal.c +119 -0
  89. data/ext/ev/timer.c +197 -0
  90. data/ext/libev/Changes +513 -0
  91. data/ext/libev/LICENSE +37 -0
  92. data/ext/libev/README +58 -0
  93. data/ext/libev/README.embed +3 -0
  94. data/ext/libev/ev.c +5214 -0
  95. data/ext/libev/ev.h +849 -0
  96. data/ext/libev/ev_epoll.c +285 -0
  97. data/ext/libev/ev_kqueue.c +218 -0
  98. data/ext/libev/ev_poll.c +151 -0
  99. data/ext/libev/ev_port.c +189 -0
  100. data/ext/libev/ev_select.c +316 -0
  101. data/ext/libev/ev_vars.h +204 -0
  102. data/ext/libev/ev_win32.c +162 -0
  103. data/ext/libev/ev_wrap.h +200 -0
  104. data/ext/libev/test_libev_win32.c +123 -0
  105. data/lib/polyphony.rb +7 -2
  106. data/lib/polyphony/core.rb +1 -1
  107. data/lib/polyphony/core/{coroutine.rb → coprocess.rb} +10 -10
  108. data/lib/polyphony/core/exceptions.rb +5 -5
  109. data/lib/polyphony/core/supervisor.rb +16 -16
  110. data/lib/polyphony/core/thread.rb +1 -1
  111. data/lib/polyphony/extensions/io.rb +43 -42
  112. data/lib/polyphony/extensions/kernel.rb +10 -34
  113. data/lib/polyphony/extensions/postgres.rb +3 -2
  114. data/lib/polyphony/extensions/redis.rb +1 -1
  115. data/lib/polyphony/extensions/socket.rb +8 -4
  116. data/lib/polyphony/extensions/ssl.rb +0 -54
  117. data/lib/polyphony/http/agent.rb +4 -10
  118. data/lib/polyphony/http/http1.rb +25 -25
  119. data/lib/polyphony/http/http1_request.rb +38 -26
  120. data/lib/polyphony/http/http2.rb +4 -5
  121. data/lib/polyphony/http/http2_request.rb +12 -18
  122. data/lib/polyphony/http/rack.rb +1 -3
  123. data/lib/polyphony/http/server.rb +9 -9
  124. data/lib/polyphony/net.rb +2 -2
  125. data/lib/polyphony/resource_pool.rb +5 -1
  126. data/lib/polyphony/version.rb +1 -1
  127. data/lib/polyphony/websocket.rb +52 -0
  128. data/polyphony.gemspec +31 -0
  129. data/test/test_coprocess.rb +131 -0
  130. data/test/test_core.rb +274 -0
  131. data/test/test_ev.rb +117 -0
  132. data/test/test_io.rb +38 -0
  133. metadata +113 -7
  134. data/lib/polyphony/core/async.rb +0 -36
  135. data/lib/polyphony/net_old.rb +0 -299
@@ -0,0 +1,123 @@
1
+ // a single header file is required
2
+ #include <ev.h>
3
+ #include <stdio.h>
4
+ #include <io.h>
5
+
6
+ // every watcher type has its own typedef'd struct
7
+ // with the name ev_TYPE
8
+ ev_io stdin_watcher;
9
+ ev_timer timeout_watcher;
10
+
11
+ // all watcher callbacks have a similar signature
12
+ // this callback is called when data is readable on stdin
13
+ static void
14
+ stdin_cb (EV_P_ ev_io *w, int revents)
15
+ {
16
+ puts ("stdin ready or done or something");
17
+ // for one-shot events, one must manually stop the watcher
18
+ // with its corresponding stop function.
19
+ //ev_io_stop (EV_A_ w);
20
+
21
+ // this causes all nested ev_loop's to stop iterating
22
+ //ev_unloop (EV_A_ EVUNLOOP_ALL);
23
+ }
24
+
25
+ // another callback, this time for a time-out
26
+ static void
27
+ timeout_cb (EV_P_ ev_timer *w, int revents)
28
+ {
29
+ puts ("timeout");
30
+ // this causes the innermost ev_loop to stop iterating
31
+ ev_unloop (EV_A_ EVUNLOOP_ONE);
32
+ }
33
+
34
+
35
+
36
+ #include <winsock.h>
37
+
38
+ #include <stdlib.h>
39
+ #include <iostream>
40
+ int get_server_fd()
41
+ {
42
+
43
+ //----------------------
44
+ // Initialize Winsock.
45
+ WSADATA wsaData;
46
+ int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
47
+ if (iResult != NO_ERROR) {
48
+ printf("Error at WSAStartup()\n");
49
+ return 1;
50
+ }
51
+
52
+ //----------------------
53
+ // Create a SOCKET for listening for
54
+ // incoming connection requests.
55
+ SOCKET ListenSocket;
56
+ ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
57
+ if (ListenSocket == INVALID_SOCKET) {
58
+ printf("Error at socket(): %ld\n", WSAGetLastError());
59
+ WSACleanup();
60
+ return 1;
61
+ }
62
+ printf("socket returned %d\n", ListenSocket);
63
+
64
+ //----------------------
65
+ // The sockaddr_in structure specifies the address family,
66
+ // IP address, and port for the socket that is being bound.
67
+ sockaddr_in service;
68
+ service.sin_family = AF_INET;
69
+ service.sin_addr.s_addr = inet_addr("127.0.0.1");
70
+ service.sin_port = htons(4444);
71
+
72
+ if (bind( ListenSocket,
73
+ (SOCKADDR*) &service,
74
+ sizeof(service)) == SOCKET_ERROR) {
75
+ printf("bind() failed.\n");
76
+ closesocket(ListenSocket);
77
+ WSACleanup();
78
+ return 1;
79
+ }
80
+
81
+ //----------------------
82
+ // Listen for incoming connection requests.
83
+ // on the created socket
84
+ if (listen( ListenSocket, 1 ) == SOCKET_ERROR) {
85
+ printf("Error listening on socket.\n");
86
+ closesocket(ListenSocket);
87
+ WSACleanup();
88
+ return 1;
89
+ }
90
+
91
+
92
+ printf("sock and osf handle are %d %d, error is \n", ListenSocket, _get_osfhandle (ListenSocket)); // -1 is invalid file handle: http://msdn.microsoft.com/en-us/library/ks2530z6.aspx
93
+ printf("err was %d\n", WSAGetLastError());
94
+ //----------------------
95
+ return ListenSocket;
96
+ }
97
+
98
+
99
+ int
100
+ main (void)
101
+ {
102
+ struct ev_loop *loopy = ev_default_loop(0);
103
+ int fd = get_server_fd();
104
+ int fd_real = _open_osfhandle(fd, NULL);
105
+ int conv = _get_osfhandle(fd_real);
106
+ printf("got server fd %d, loop %d, fd_real %d, that converted %d\n", fd, loopy, fd_real, conv);
107
+ // accept(fd, NULL, NULL);
108
+ // initialise an io watcher, then start it
109
+ // this one will watch for stdin to become readable
110
+ ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ conv, EV_READ);
111
+ ev_io_start (loopy, &stdin_watcher);
112
+
113
+ // initialise a timer watcher, then start it
114
+ // simple non-repeating 5.5 second timeout
115
+ //ev_timer_init (&timeout_watcher, timeout_cb, 15.5, 0.);
116
+ //ev_timer_start (loopy, &timeout_watcher);
117
+ printf("starting loop\n");
118
+ // now wait for events to arrive
119
+ ev_loop (loopy, 0);
120
+
121
+ // unloop was called, so exit
122
+ return 0;
123
+ }
@@ -7,19 +7,24 @@ export_default :Polyphony
7
7
  Polyphony = import('./polyphony/core')
8
8
  Exceptions = import('./polyphony/core/exceptions')
9
9
 
10
+ import('polyphony/extensions/socket')
11
+ import('polyphony/extensions/ssl')
12
+
10
13
  module Polyphony
11
14
  Cancel = Exceptions::Cancel
12
15
  MoveOn = Exceptions::MoveOn
13
16
 
17
+ Net = import('./polyphony/net')
18
+
14
19
  auto_import(
15
20
  Channel: './polyphony/core/channel',
16
- Coroutine: './polyphony/core/coroutine',
21
+ Coprocess: './polyphony/core/coprocess',
17
22
  Sync: './polyphony/core/sync',
18
23
  Thread: './polyphony/core/thread',
19
24
  ThreadPool: './polyphony/core/thread_pool',
20
25
 
21
26
  FS: './polyphony/fs',
22
- Net: './polyphony/net',
27
+ # Net: './polyphony/net',
23
28
  ResourcePool: './polyphony/resource_pool',
24
29
  Supervisor: './polyphony/supervisor'
25
30
  )
@@ -22,7 +22,7 @@ module Core
22
22
  pid = Kernel.fork do
23
23
  FiberPool.reset!
24
24
  EV.post_fork
25
- Fiber.current.coroutine = Coroutine.new(Fiber.current)
25
+ Fiber.current.coprocess = Coprocess.new(Fiber.current)
26
26
 
27
27
  block.()
28
28
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- export_default :Coroutine
3
+ export_default :Coprocess
4
4
 
5
5
  import('../extensions/kernel')
6
6
 
@@ -8,7 +8,7 @@ FiberPool = import('./fiber_pool')
8
8
  Exceptions = import('./exceptions')
9
9
 
10
10
  # Encapsulates an asynchronous task
11
- class Coroutine
11
+ class Coprocess
12
12
  attr_reader :result, :fiber
13
13
 
14
14
 
@@ -21,7 +21,7 @@ class Coroutine
21
21
  @caller = caller if Exceptions.debug
22
22
 
23
23
  @fiber = FiberPool.spawn do
24
- @fiber.coroutine = self
24
+ @fiber.coprocess = self
25
25
  @result = (@block || block2).call(self)
26
26
  rescue Exceptions::MoveOn, Exceptions::Stop => e
27
27
  @result = e.value
@@ -29,7 +29,7 @@ class Coroutine
29
29
  e.cleanup_backtrace(@caller) if Exceptions.debug
30
30
  @result = e
31
31
  ensure
32
- @fiber.coroutine = nil
32
+ @fiber.coprocess = nil
33
33
  @fiber = nil
34
34
  @awaiting_fiber&.schedule @result
35
35
  @when_done&.()
@@ -66,7 +66,7 @@ class Coroutine
66
66
  end
67
67
 
68
68
  # Kernel.await expects the given argument / block to be a callable, so #call
69
- # in fact waits for the coroutine to finish
69
+ # in fact waits for the coprocess to finish
70
70
  def await
71
71
  run unless @ran
72
72
  if @fiber
@@ -76,7 +76,7 @@ class Coroutine
76
76
  @result
77
77
  end
78
78
  ensure
79
- # if awaiting was interrupted and the coroutine is still running, we need to stop it
79
+ # if awaiting was interrupted and the coprocess is still running, we need to stop it
80
80
  if @fiber
81
81
  @fiber&.schedule(Exceptions::MoveOn.new)
82
82
  suspend
@@ -91,16 +91,16 @@ class Coroutine
91
91
  @fiber&.schedule(value)
92
92
  end
93
93
 
94
- def interrupt(value = Exceptions::MoveOn.new)
95
- @fiber&.schedule(value)
94
+ def interrupt(value = nil)
95
+ @fiber&.schedule(Exceptions::MoveOn.new(nil, value))
96
96
  end
97
97
  alias_method :stop, :interrupt
98
98
 
99
99
  def cancel!
100
- interrupt(Exceptions::Cancel.new)
100
+ @fiber&.schedule(Exceptions::Cancel.new)
101
101
  end
102
102
 
103
103
  def self.current
104
- Fiber.current.coroutine
104
+ Fiber.current.coprocess
105
105
  end
106
106
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- export :CoroutineInterrupt, :MoveOn, :Stop, :Cancel, :debug, :debug=
3
+ export :CoprocessInterrupt, :MoveOn, :Stop, :Cancel, :debug, :debug=
4
4
 
5
- class CoroutineInterrupt < ::Exception
5
+ class CoprocessInterrupt < ::Exception
6
6
  attr_reader :scope, :value
7
7
 
8
8
  def initialize(scope = nil, value = nil)
@@ -11,9 +11,9 @@ class CoroutineInterrupt < ::Exception
11
11
  end
12
12
  end
13
13
 
14
- class Stop < CoroutineInterrupt; end
15
- class MoveOn < CoroutineInterrupt; end
16
- class Cancel < CoroutineInterrupt; end
14
+ class Stop < CoprocessInterrupt; end
15
+ class MoveOn < CoprocessInterrupt; end
16
+ class Cancel < CoprocessInterrupt; end
17
17
 
18
18
  def debug
19
19
  @debug
@@ -2,12 +2,12 @@
2
2
 
3
3
  export_default :Supervisor
4
4
 
5
- Coroutine = import('./coroutine')
5
+ Coprocess = import('./coprocess')
6
6
  Exceptions = import('./exceptions')
7
7
 
8
8
  class Supervisor
9
9
  def initialize
10
- @coroutines = []
10
+ @coprocesss = []
11
11
  end
12
12
 
13
13
  def await(&block)
@@ -26,31 +26,31 @@ class Supervisor
26
26
  end
27
27
 
28
28
  def spawn(proc = nil, &block)
29
- if proc.is_a?(Coroutine)
30
- spawn_coroutine(proc)
29
+ if proc.is_a?(Coprocess)
30
+ spawn_coprocess(proc)
31
31
  else
32
32
  spawn_proc(block || proc)
33
33
  end
34
34
  end
35
35
 
36
- def spawn_coroutine(proc)
37
- @coroutines << proc
36
+ def spawn_coprocess(proc)
37
+ @coprocesss << proc
38
38
  proc.when_done { task_completed(proc) }
39
39
  proc.run unless proc.running?
40
40
  proc
41
41
  end
42
42
 
43
43
  def spawn_proc(proc)
44
- @coroutines << Object.spawn do |coroutine|
45
- proc.call(coroutine)
46
- task_completed(coroutine)
44
+ @coprocesss << Object.spawn do |coprocess|
45
+ proc.call(coprocess)
46
+ task_completed(coprocess)
47
47
  rescue Exception => e
48
- task_completed(coroutine)
48
+ task_completed(coprocess)
49
49
  end
50
50
  end
51
51
 
52
52
  def still_running?
53
- !@coroutines.empty?
53
+ !@coprocesss.empty?
54
54
  end
55
55
 
56
56
  def stop!(result = nil)
@@ -61,15 +61,15 @@ class Supervisor
61
61
 
62
62
  def stop_all_tasks
63
63
  exception = Exceptions::Stop.new
64
- @coroutines.each do |c|
64
+ @coprocesss.each do |c|
65
65
  EV.next_tick { c.interrupt(exception) }
66
66
  end
67
67
  end
68
68
 
69
- def task_completed(coroutine)
70
- return unless @coroutines.include?(coroutine)
69
+ def task_completed(coprocess)
70
+ return unless @coprocesss.include?(coprocess)
71
71
 
72
- @coroutines.delete(coroutine)
73
- @supervisor_fiber&.transfer if @coroutines.empty?
72
+ @coprocesss.delete(coprocess)
73
+ @supervisor_fiber&.transfer if @coprocesss.empty?
74
74
  end
75
75
  end
@@ -23,7 +23,7 @@ end
23
23
 
24
24
  def wait_for_thread(ctx)
25
25
  suspend
26
- rescue Exceptions::CoroutineInterrupt => e
26
+ rescue Exceptions::CoprocessInterrupt => e
27
27
  ctx[:fiber] = nil
28
28
  ctx[:thread]&.raise(e)
29
29
  raise e
@@ -14,49 +14,50 @@ class ::IO
14
14
  @write_watcher&.stop
15
15
  end
16
16
 
17
- NO_EXCEPTION = { exception: false }.freeze
17
+ # NO_EXCEPTION = { exception: false }.freeze
18
18
 
19
- def read(max = 8192, outbuf = nil)
20
- outbuf ||= (@read_buffer ||= +'')
21
- loop do
22
- result = read_nonblock(max, outbuf, NO_EXCEPTION)
23
- case result
24
- when nil then raise IOError
25
- when :wait_readable then read_watcher.await
26
- else return result
27
- end
28
- end
29
- ensure
30
- @read_watcher&.stop
31
- end
19
+ # def read(max = 8192, outbuf = nil)
20
+ # outbuf ||= (@read_buffer ||= +'')
21
+ # loop do
22
+ # result = read_nonblock(max, outbuf, NO_EXCEPTION)
23
+ # case result
24
+ # when nil then raise IOError
25
+ # when :wait_readable then read_watcher.await
26
+ # else return result
27
+ # end
28
+ # end
29
+ # ensure
30
+ # @read_watcher&.stop
31
+ # end
32
32
 
33
- def write(data)
34
- loop do
35
- result = write_nonblock(data, NO_EXCEPTION)
36
- case result
37
- when nil then raise IOError
38
- when :wait_writable then write_watcher.await
39
- else
40
- (result == data.bytesize) ? (return result) : (data = data[result..-1])
41
- end
42
- end
43
- ensure
44
- @write_watcher&.stop
45
- end
33
+ # def write(data)
34
+ # loop do
35
+ # result = write_nonblock(data, NO_EXCEPTION)
36
+ # case result
37
+ # when nil then raise IOError
38
+ # when :wait_writable then write_watcher.await
39
+ # else
40
+ # (result == data.bytesize) ? (return result) : (data = data[result..-1])
41
+ # end
42
+ # end
43
+ # ensure
44
+ # @write_watcher&.stop
45
+ # end
46
46
 
47
- def write_list(*list)
48
- list.each do |data|
49
- loop do
50
- result = write_nonblock(data, NO_EXCEPTION)
51
- case result
52
- when nil then raise IOError
53
- when :wait_writable then write_watcher.await
54
- else
55
- (result == data.bytesize) ? (break result) : (data = data[result..-1])
56
- end
57
- end
58
- end
59
- ensure
60
- @write_watcher&.stop
61
- end
47
+ # # write_list is inspired by
48
+ # def write_list(*list)
49
+ # list.each do |data|
50
+ # loop do
51
+ # result = write_nonblock(data, NO_EXCEPTION)
52
+ # case result
53
+ # when nil then raise IOError
54
+ # when :wait_writable then write_watcher.await
55
+ # else
56
+ # (result == data.bytesize) ? (break result) : (data = data[result..-1])
57
+ # end
58
+ # end
59
+ # end
60
+ # ensure
61
+ # @write_watcher&.stop
62
+ # end
62
63
  end
@@ -3,7 +3,7 @@
3
3
  require 'fiber'
4
4
 
5
5
  CancelScope = import('../core/cancel_scope')
6
- Coroutine = import('../core/coroutine')
6
+ Coprocess = import('../core/coprocess')
7
7
  Exceptions = import('../core/exceptions')
8
8
  Supervisor = import('../core/supervisor')
9
9
  Throttler = import('../core/throttler')
@@ -11,33 +11,18 @@ Throttler = import('../core/throttler')
11
11
  # Fiber extensions
12
12
  class ::Fiber
13
13
  attr_writer :cancelled
14
- attr_accessor :next_job, :coroutine
14
+ attr_accessor :next_job, :coprocess
15
15
 
16
16
  def cancelled?
17
17
  @cancelled
18
18
  end
19
19
 
20
- def root?
21
- @root
22
- end
23
-
24
20
  def schedule(value = nil)
25
21
  EV.schedule_fiber(self, value)
26
22
  end
27
23
 
28
- def set_root!
29
- @root = true
30
- end
31
-
32
- def self.root
33
- @@root
34
- end
35
-
36
- @@root = Fiber.current
37
- @@root.set_root!
38
-
39
- # Associate a (pseudo-)coroutine with the main fiber
40
- current.coroutine = Coroutine.new(Fiber.current)
24
+ # Associate a (pseudo-)coprocess with the main fiber
25
+ current.coprocess = Coprocess.new(current)
41
26
  end
42
27
 
43
28
  class ::Exception
@@ -60,7 +45,7 @@ module ::Kernel
60
45
  if sym
61
46
  async_decorate(is_a?(Class) ? self : singleton_class, sym)
62
47
  else
63
- Coroutine.new(&block)
48
+ Coprocess.new(&block)
64
49
  end
65
50
  end
66
51
 
@@ -72,9 +57,7 @@ module ::Kernel
72
57
  def async_decorate(receiver, sym)
73
58
  sync_sym = :"sync_#{sym}"
74
59
  receiver.alias_method(sync_sym, sym)
75
- receiver.define_method(sym) do |*args, &block|
76
- Coroutine.new { send(sync_sym, *args, &block) }
77
- end
60
+ receiver.class_eval("def #{sym}(*args, &block); Coprocess.new { send(#{sync_sym.inspect}, *args, &block) }; end")
78
61
  end
79
62
 
80
63
  def cancel_after(duration, &block)
@@ -113,7 +96,7 @@ module ::Kernel
113
96
  end
114
97
 
115
98
  def receive
116
- Fiber.current.coroutine.receive
99
+ Fiber.current.coprocess.receive
117
100
  end
118
101
 
119
102
  alias_method :sync_sleep, :sleep
@@ -125,10 +108,10 @@ module ::Kernel
125
108
  end
126
109
 
127
110
  def spawn(proc = nil, &block)
128
- if proc.is_a?(Coroutine)
111
+ if proc.is_a?(Coprocess)
129
112
  proc.run
130
113
  else
131
- Coroutine.new(&(block || proc)).run
114
+ Coprocess.new(&(block || proc)).run
132
115
  end
133
116
  end
134
117
 
@@ -136,13 +119,6 @@ module ::Kernel
136
119
  Supervisor.new.await(&block)
137
120
  end
138
121
 
139
- # @@reactor_fiber = Fiber.root
140
-
141
- # def suspend
142
- # result = @@reactor_fiber.transfer
143
- # result.is_a?(Exception) ? raise(result) : result
144
- # end
145
-
146
122
  def throttled_loop(rate, &block)
147
123
  throttler = Throttler.new(rate)
148
124
  loop do
@@ -155,7 +131,7 @@ module ::Kernel
155
131
  end
156
132
 
157
133
  def timeout(duration, opts = {}, &block)
158
- CancelScope.new(opts.merge(timeout: duration)).(&block)
134
+ CancelScope.new(**opts, timeout: duration).(&block)
159
135
  end
160
136
  end
161
137