polyphony 0.43.8

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.
Files changed (221) hide show
  1. checksums.yaml +7 -0
  2. data/.gitbook.yaml +4 -0
  3. data/.github/workflows/test.yml +29 -0
  4. data/.gitignore +59 -0
  5. data/.rubocop.yml +175 -0
  6. data/CHANGELOG.md +393 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +141 -0
  9. data/LICENSE +21 -0
  10. data/README.md +51 -0
  11. data/Rakefile +26 -0
  12. data/TODO.md +201 -0
  13. data/bin/polyphony-debug +87 -0
  14. data/docs/_config.yml +64 -0
  15. data/docs/_includes/head.html +40 -0
  16. data/docs/_includes/title.html +1 -0
  17. data/docs/_sass/custom/custom.scss +10 -0
  18. data/docs/_sass/overrides.scss +0 -0
  19. data/docs/_user-guide/all-about-timers.md +126 -0
  20. data/docs/_user-guide/index.md +9 -0
  21. data/docs/_user-guide/web-server.md +136 -0
  22. data/docs/api-reference/exception.md +27 -0
  23. data/docs/api-reference/fiber.md +425 -0
  24. data/docs/api-reference/index.md +9 -0
  25. data/docs/api-reference/io.md +36 -0
  26. data/docs/api-reference/object.md +99 -0
  27. data/docs/api-reference/polyphony-baseexception.md +33 -0
  28. data/docs/api-reference/polyphony-cancel.md +26 -0
  29. data/docs/api-reference/polyphony-moveon.md +24 -0
  30. data/docs/api-reference/polyphony-net.md +20 -0
  31. data/docs/api-reference/polyphony-process.md +28 -0
  32. data/docs/api-reference/polyphony-resourcepool.md +59 -0
  33. data/docs/api-reference/polyphony-restart.md +18 -0
  34. data/docs/api-reference/polyphony-terminate.md +18 -0
  35. data/docs/api-reference/polyphony-threadpool.md +67 -0
  36. data/docs/api-reference/polyphony-throttler.md +77 -0
  37. data/docs/api-reference/polyphony.md +36 -0
  38. data/docs/api-reference/thread.md +88 -0
  39. data/docs/assets/img/echo-fibers.svg +1 -0
  40. data/docs/assets/img/sleeping-fiber.svg +1 -0
  41. data/docs/faq.md +195 -0
  42. data/docs/favicon.ico +0 -0
  43. data/docs/getting-started/index.md +10 -0
  44. data/docs/getting-started/installing.md +34 -0
  45. data/docs/getting-started/overview.md +486 -0
  46. data/docs/getting-started/tutorial.md +359 -0
  47. data/docs/index.md +94 -0
  48. data/docs/main-concepts/concurrency.md +151 -0
  49. data/docs/main-concepts/design-principles.md +161 -0
  50. data/docs/main-concepts/exception-handling.md +291 -0
  51. data/docs/main-concepts/extending.md +89 -0
  52. data/docs/main-concepts/fiber-scheduling.md +197 -0
  53. data/docs/main-concepts/index.md +9 -0
  54. data/docs/polyphony-logo.png +0 -0
  55. data/examples/adapters/concurrent-ruby.rb +9 -0
  56. data/examples/adapters/pg_client.rb +36 -0
  57. data/examples/adapters/pg_notify.rb +35 -0
  58. data/examples/adapters/pg_pool.rb +43 -0
  59. data/examples/adapters/pg_transaction.rb +31 -0
  60. data/examples/adapters/redis_blpop.rb +12 -0
  61. data/examples/adapters/redis_channels.rb +122 -0
  62. data/examples/adapters/redis_client.rb +19 -0
  63. data/examples/adapters/redis_pubsub.rb +26 -0
  64. data/examples/adapters/redis_pubsub_perf.rb +68 -0
  65. data/examples/core/01-spinning-up-fibers.rb +18 -0
  66. data/examples/core/02-awaiting-fibers.rb +20 -0
  67. data/examples/core/03-interrupting.rb +39 -0
  68. data/examples/core/04-handling-signals.rb +19 -0
  69. data/examples/core/xx-agent.rb +102 -0
  70. data/examples/core/xx-at_exit.rb +29 -0
  71. data/examples/core/xx-caller.rb +12 -0
  72. data/examples/core/xx-channels.rb +45 -0
  73. data/examples/core/xx-daemon.rb +14 -0
  74. data/examples/core/xx-deadlock.rb +8 -0
  75. data/examples/core/xx-deferring-an-operation.rb +14 -0
  76. data/examples/core/xx-erlang-style-genserver.rb +81 -0
  77. data/examples/core/xx-exception-backtrace.rb +40 -0
  78. data/examples/core/xx-fork-cleanup.rb +22 -0
  79. data/examples/core/xx-fork-spin.rb +42 -0
  80. data/examples/core/xx-fork-terminate.rb +27 -0
  81. data/examples/core/xx-forking.rb +24 -0
  82. data/examples/core/xx-move_on.rb +23 -0
  83. data/examples/core/xx-pingpong.rb +18 -0
  84. data/examples/core/xx-queue-async.rb +120 -0
  85. data/examples/core/xx-readpartial.rb +18 -0
  86. data/examples/core/xx-recurrent-timer.rb +12 -0
  87. data/examples/core/xx-resource_delegate.rb +31 -0
  88. data/examples/core/xx-signals.rb +16 -0
  89. data/examples/core/xx-sleep-forever.rb +9 -0
  90. data/examples/core/xx-sleeping.rb +25 -0
  91. data/examples/core/xx-snooze-starve.rb +16 -0
  92. data/examples/core/xx-spin-fork.rb +49 -0
  93. data/examples/core/xx-spin_error_backtrace.rb +33 -0
  94. data/examples/core/xx-state-machine.rb +51 -0
  95. data/examples/core/xx-stop.rb +20 -0
  96. data/examples/core/xx-supervise-process.rb +30 -0
  97. data/examples/core/xx-supervisors.rb +21 -0
  98. data/examples/core/xx-thread-selector-sleep.rb +51 -0
  99. data/examples/core/xx-thread-selector-snooze.rb +46 -0
  100. data/examples/core/xx-thread-sleep.rb +17 -0
  101. data/examples/core/xx-thread-snooze.rb +34 -0
  102. data/examples/core/xx-thread_pool.rb +17 -0
  103. data/examples/core/xx-throttling.rb +18 -0
  104. data/examples/core/xx-timeout.rb +10 -0
  105. data/examples/core/xx-timer-gc.rb +17 -0
  106. data/examples/core/xx-trace.rb +79 -0
  107. data/examples/core/xx-using-a-mutex.rb +21 -0
  108. data/examples/core/xx-worker-thread.rb +30 -0
  109. data/examples/io/tunnel.rb +48 -0
  110. data/examples/io/xx-backticks.rb +11 -0
  111. data/examples/io/xx-echo_client.rb +25 -0
  112. data/examples/io/xx-echo_client_from_stdin.rb +21 -0
  113. data/examples/io/xx-echo_pipe.rb +16 -0
  114. data/examples/io/xx-echo_server.rb +17 -0
  115. data/examples/io/xx-echo_server_with_timeout.rb +34 -0
  116. data/examples/io/xx-echo_stdin.rb +14 -0
  117. data/examples/io/xx-happy-eyeballs.rb +36 -0
  118. data/examples/io/xx-httparty.rb +38 -0
  119. data/examples/io/xx-irb.rb +17 -0
  120. data/examples/io/xx-net-http.rb +15 -0
  121. data/examples/io/xx-open.rb +16 -0
  122. data/examples/io/xx-switch.rb +15 -0
  123. data/examples/io/xx-system.rb +11 -0
  124. data/examples/io/xx-tcpserver.rb +15 -0
  125. data/examples/io/xx-tcpsocket.rb +18 -0
  126. data/examples/io/xx-zip.rb +19 -0
  127. data/examples/performance/fiber_transfer.rb +47 -0
  128. data/examples/performance/fs_read.rb +38 -0
  129. data/examples/performance/mem-usage.rb +56 -0
  130. data/examples/performance/messaging.rb +29 -0
  131. data/examples/performance/multi_snooze.rb +33 -0
  132. data/examples/performance/snooze.rb +39 -0
  133. data/examples/performance/snooze_raw.rb +39 -0
  134. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +74 -0
  135. data/examples/performance/thread-vs-fiber/polyphony_server.rb +45 -0
  136. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +58 -0
  137. data/examples/performance/thread-vs-fiber/threaded_server.rb +27 -0
  138. data/examples/performance/thread-vs-fiber/xx-httparty_multi.rb +36 -0
  139. data/examples/performance/thread-vs-fiber/xx-httparty_threaded.rb +29 -0
  140. data/examples/performance/thread_pool_perf.rb +63 -0
  141. data/examples/performance/xx-array.rb +11 -0
  142. data/examples/performance/xx-fiber-switch.rb +9 -0
  143. data/examples/performance/xx-snooze.rb +15 -0
  144. data/examples/xx-spin.rb +32 -0
  145. data/ext/libev/Changes +548 -0
  146. data/ext/libev/LICENSE +37 -0
  147. data/ext/libev/README +59 -0
  148. data/ext/libev/README.embed +3 -0
  149. data/ext/libev/ev.c +5279 -0
  150. data/ext/libev/ev.h +856 -0
  151. data/ext/libev/ev_epoll.c +296 -0
  152. data/ext/libev/ev_kqueue.c +224 -0
  153. data/ext/libev/ev_linuxaio.c +642 -0
  154. data/ext/libev/ev_poll.c +156 -0
  155. data/ext/libev/ev_port.c +192 -0
  156. data/ext/libev/ev_select.c +316 -0
  157. data/ext/libev/ev_vars.h +215 -0
  158. data/ext/libev/ev_win32.c +162 -0
  159. data/ext/libev/ev_wrap.h +216 -0
  160. data/ext/libev/test_libev_win32.c +123 -0
  161. data/ext/polyphony/extconf.rb +20 -0
  162. data/ext/polyphony/fiber.c +109 -0
  163. data/ext/polyphony/libev.c +2 -0
  164. data/ext/polyphony/libev.h +9 -0
  165. data/ext/polyphony/libev_agent.c +882 -0
  166. data/ext/polyphony/polyphony.c +71 -0
  167. data/ext/polyphony/polyphony.h +97 -0
  168. data/ext/polyphony/polyphony_ext.c +21 -0
  169. data/ext/polyphony/queue.c +168 -0
  170. data/ext/polyphony/ring_buffer.c +96 -0
  171. data/ext/polyphony/ring_buffer.h +28 -0
  172. data/ext/polyphony/thread.c +208 -0
  173. data/ext/polyphony/tracing.c +11 -0
  174. data/lib/polyphony.rb +136 -0
  175. data/lib/polyphony/adapters/fs.rb +19 -0
  176. data/lib/polyphony/adapters/irb.rb +52 -0
  177. data/lib/polyphony/adapters/postgres.rb +110 -0
  178. data/lib/polyphony/adapters/process.rb +33 -0
  179. data/lib/polyphony/adapters/redis.rb +67 -0
  180. data/lib/polyphony/adapters/trace.rb +138 -0
  181. data/lib/polyphony/core/channel.rb +46 -0
  182. data/lib/polyphony/core/exceptions.rb +36 -0
  183. data/lib/polyphony/core/global_api.rb +124 -0
  184. data/lib/polyphony/core/resource_pool.rb +117 -0
  185. data/lib/polyphony/core/sync.rb +21 -0
  186. data/lib/polyphony/core/thread_pool.rb +64 -0
  187. data/lib/polyphony/core/throttler.rb +41 -0
  188. data/lib/polyphony/event.rb +17 -0
  189. data/lib/polyphony/extensions/core.rb +174 -0
  190. data/lib/polyphony/extensions/fiber.rb +379 -0
  191. data/lib/polyphony/extensions/io.rb +221 -0
  192. data/lib/polyphony/extensions/openssl.rb +81 -0
  193. data/lib/polyphony/extensions/socket.rb +150 -0
  194. data/lib/polyphony/extensions/thread.rb +108 -0
  195. data/lib/polyphony/net.rb +77 -0
  196. data/lib/polyphony/version.rb +5 -0
  197. data/polyphony.gemspec +40 -0
  198. data/test/coverage.rb +54 -0
  199. data/test/eg.rb +27 -0
  200. data/test/helper.rb +56 -0
  201. data/test/q.rb +24 -0
  202. data/test/run.rb +5 -0
  203. data/test/stress.rb +25 -0
  204. data/test/test_agent.rb +130 -0
  205. data/test/test_event.rb +59 -0
  206. data/test/test_ext.rb +196 -0
  207. data/test/test_fiber.rb +988 -0
  208. data/test/test_global_api.rb +352 -0
  209. data/test/test_io.rb +249 -0
  210. data/test/test_kernel.rb +57 -0
  211. data/test/test_process_supervision.rb +46 -0
  212. data/test/test_queue.rb +112 -0
  213. data/test/test_resource_pool.rb +138 -0
  214. data/test/test_signal.rb +100 -0
  215. data/test/test_socket.rb +34 -0
  216. data/test/test_supervise.rb +103 -0
  217. data/test/test_thread.rb +170 -0
  218. data/test/test_thread_pool.rb +101 -0
  219. data/test/test_throttler.rb +50 -0
  220. data/test/test_trace.rb +68 -0
  221. metadata +482 -0
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+
5
+ # IO class method patches
6
+ class ::IO
7
+ class << self
8
+ alias_method :orig_binread, :binread
9
+ def binread(name, length = nil, offset = nil)
10
+ File.open(name, 'rb:ASCII-8BIT') do |f|
11
+ f.seek(offset) if offset
12
+ length ? f.read(length) : f.read
13
+ end
14
+ end
15
+
16
+ alias_method :orig_binwrite, :binwrite
17
+ def binwrite(name, string, offset = nil)
18
+ File.open(name, 'wb:ASCII-8BIT') do |f|
19
+ f.seek(offset) if offset
20
+ f.write(string)
21
+ end
22
+ end
23
+
24
+ EMPTY_HASH = {}.freeze
25
+
26
+ # alias_method :orig_foreach, :foreach
27
+ # def foreach(_name, _sep = $/, _limit = nil, _getline_args = EMPTY_HASH,
28
+ # &_block)
29
+ # # IO.orig_read(name).each_line(&block)
30
+ # raise NotImplementedError
31
+
32
+ # # if sep.is_a?(Integer)
33
+ # # sep = $/
34
+ # # limit = sep
35
+ # # end
36
+ # # File.open(name, 'r') do |f|
37
+ # # f.each_line(sep, limit, getline_args, &block)
38
+ # # end
39
+ # end
40
+
41
+ alias_method :orig_read, :read
42
+ def read(name, length = nil, offset = nil, opt = EMPTY_HASH)
43
+ if length.is_a?(Hash)
44
+ opt = length
45
+ length = nil
46
+ end
47
+ File.open(name, opt[:mode] || 'r') do |f|
48
+ f.seek(offset) if offset
49
+ length ? f.read(length) : f.read
50
+ end
51
+ end
52
+
53
+ # alias_method :orig_readlines, :readlines
54
+ # def readlines(name, sep = $/, limit = nil, getline_args = EMPTY_HASH)
55
+ # File.open(name, 'r') do |f|
56
+ # f.readlines(sep, limit, getline_args)
57
+ # end
58
+ # end
59
+
60
+ alias_method :orig_write, :write
61
+ def write(name, string, offset = nil, opt = EMPTY_HASH)
62
+ File.open(name, opt[:mode] || 'w') do |f|
63
+ f.seek(offset) if offset
64
+ f.write(string)
65
+ end
66
+ end
67
+
68
+ alias_method :orig_popen, :popen
69
+ def popen(cmd, mode = 'r')
70
+ return orig_popen(cmd, mode) unless block_given?
71
+
72
+ Open3.popen2(cmd) { |_i, o, _t| yield o }
73
+ end
74
+ end
75
+ end
76
+
77
+ # IO instance method patches
78
+ class ::IO
79
+ # def each(sep = $/, limit = nil, chomp: nil)
80
+ # sep, limit = $/, sep if sep.is_a?(Integer)
81
+ # end
82
+ # alias_method :each_line, :each
83
+
84
+ # def each_byte
85
+ # end
86
+
87
+ # def each_char
88
+ # end
89
+
90
+ # def each_codepoint
91
+ # end
92
+
93
+ # def getbyte
94
+ # end
95
+
96
+ # def getc
97
+ # end
98
+
99
+ alias_method :orig_read, :read
100
+ def read(len = nil)
101
+ @read_buffer ||= +''
102
+ result = Thread.current.agent.read(self, @read_buffer, len, true)
103
+ return nil unless result
104
+
105
+ already_read = @read_buffer
106
+ @read_buffer = +''
107
+ already_read
108
+ end
109
+
110
+ alias_method :orig_readpartial, :read
111
+ def readpartial(len, str = nil)
112
+ @read_buffer ||= +''
113
+ result = Thread.current.agent.read(self, @read_buffer, len, false)
114
+ raise EOFError unless result
115
+
116
+ if str
117
+ str << @read_buffer
118
+ else
119
+ str = @read_buffer
120
+ end
121
+ @read_buffer = +''
122
+ str
123
+ end
124
+
125
+ alias_method :orig_write, :write
126
+ def write(str, *args)
127
+ Thread.current.agent.write(self, str, *args)
128
+ end
129
+
130
+ alias_method :orig_write_chevron, :<<
131
+ def <<(str)
132
+ Thread.current.agent.write(self, str)
133
+ self
134
+ end
135
+
136
+ alias_method :orig_gets, :gets
137
+ def gets(sep = $/, _limit = nil, _chomp: nil)
138
+ if sep.is_a?(Integer)
139
+ sep = $/
140
+ _limit = sep
141
+ end
142
+ sep_size = sep.bytesize
143
+
144
+ @read_buffer ||= +''
145
+
146
+ loop do
147
+ idx = @read_buffer.index(sep)
148
+ return @read_buffer.slice!(0, idx + sep_size) if idx
149
+
150
+ data = readpartial(8192)
151
+ @read_buffer << data
152
+ rescue EOFError
153
+ return nil
154
+ end
155
+ end
156
+
157
+ # def print(*args)
158
+ # end
159
+
160
+ # def printf(format, *args)
161
+ # end
162
+
163
+ # def putc(obj)
164
+ # end
165
+
166
+ alias_method :orig_puts, :puts
167
+ def puts(*args)
168
+ if args.empty?
169
+ write "\n"
170
+ return
171
+ end
172
+
173
+ strs = args.inject([]) do |m, a|
174
+ a = a.to_s
175
+ m << a
176
+ m << "\n" unless a =~ /\n$/
177
+ m
178
+ end
179
+ write *strs
180
+ nil
181
+ end
182
+
183
+ # def readbyte
184
+ # end
185
+
186
+ # def readchar
187
+ # end
188
+
189
+ # def readline(sep = $/, limit = nil, chomp: nil)
190
+ # end
191
+
192
+ # def readlines(sep = $/, limit = nil, chomp: nil)
193
+ # end
194
+
195
+ alias_method :orig_write_nonblock, :write_nonblock
196
+ def write_nonblock(string, _options = {})
197
+ write(string)
198
+ end
199
+
200
+ alias_method :orig_read_nonblock, :read_nonblock
201
+ def read_nonblock(maxlen, buf = nil, _options = nil)
202
+ buf ? readpartial(maxlen, buf) : readpartial(maxlen)
203
+ end
204
+
205
+ def read_loop(&block)
206
+ Thread.current.agent.read_loop(self, &block)
207
+ end
208
+
209
+ # alias_method :orig_read, :read
210
+ # def read(length = nil, outbuf = nil)
211
+ # if length
212
+ # return outbuf ? readpartial(length) : readpartial(length, outbuf)
213
+ # end
214
+
215
+ # until eof?
216
+ # outbuf ||= +''
217
+ # outbuf << readpartial(8192)
218
+ # end
219
+ # outbuf
220
+ # end
221
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+ require_relative './socket'
5
+
6
+ # Open ssl socket helper methods (to make it compatible with Socket API)
7
+ class ::OpenSSL::SSL::SSLSocket
8
+ alias_method :orig_initialize, :initialize
9
+ def initialize(socket, context = nil)
10
+ socket = socket.respond_to?(:io) ? socket.io || socket : socket
11
+ context ? orig_initialize(socket, context) : orig_initialize(socket)
12
+ end
13
+
14
+ def dont_linger
15
+ io.dont_linger
16
+ end
17
+
18
+ def no_delay
19
+ io.no_delay
20
+ end
21
+
22
+ def reuse_addr
23
+ io.reuse_addr
24
+ end
25
+
26
+ alias_method :orig_accept, :accept
27
+ def accept
28
+ loop do
29
+ result = accept_nonblock(exception: false)
30
+ case result
31
+ when :wait_readable then Thread.current.agent.wait_io(io, false)
32
+ when :wait_writable then Thread.current.agent.wait_io(io, true)
33
+ else
34
+ return result
35
+ end
36
+ end
37
+ end
38
+
39
+ alias_method :orig_sysread, :sysread
40
+ def sysread(maxlen, buf = +'')
41
+ loop do
42
+ case (result = read_nonblock(maxlen, buf, exception: false))
43
+ when :wait_readable then Thread.current.agent.wait_io(io, false)
44
+ when :wait_writable then Thread.current.agent.wait_io(io, true)
45
+ else return result
46
+ end
47
+ end
48
+ end
49
+
50
+ alias_method :orig_syswrite, :syswrite
51
+ def syswrite(buf)
52
+ loop do
53
+ case (result = write_nonblock(buf, exception: false))
54
+ when :wait_readable then Thread.current.agent.wait_io(io, false)
55
+ when :wait_writable then Thread.current.agent.wait_io(io, true)
56
+ else
57
+ return result
58
+ end
59
+ end
60
+ end
61
+
62
+ def flush
63
+ # osync = @sync
64
+ # @sync = true
65
+ # do_write ""
66
+ # return self
67
+ # ensure
68
+ # @sync = osync
69
+ end
70
+
71
+ def readpartial(maxlen, buf = +'')
72
+ result = sysread(maxlen, buf)
73
+ result || (raise EOFError)
74
+ end
75
+
76
+ def read_loop
77
+ while (data = sysread(8192))
78
+ yield data
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'socket'
4
+
5
+ require_relative './io'
6
+ require_relative '../core/thread_pool'
7
+
8
+ class ::BasicSocket
9
+ def write_nonblock(string, _options = {})
10
+ write(string)
11
+ end
12
+
13
+ def read_nonblock(maxlen, str = nil, _options = {})
14
+ readpartial(maxlen, str)
15
+ end
16
+ end
17
+
18
+ # Socket overrides (eventually rewritten in C)
19
+ class ::Socket
20
+ def accept
21
+ Thread.current.agent.accept(self)
22
+ end
23
+
24
+ NO_EXCEPTION = { exception: false }.freeze
25
+
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
36
+ end
37
+
38
+ def recv(maxlen, flags = 0, outbuf = nil)
39
+ outbuf ||= +''
40
+ loop do
41
+ result = recv_nonblock(maxlen, flags, outbuf, **NO_EXCEPTION)
42
+ case result
43
+ when nil then raise IOError
44
+ when :wait_readable then Thread.current.agent.wait_io(self, false)
45
+ else
46
+ return result
47
+ end
48
+ end
49
+ end
50
+
51
+ def recvfrom(maxlen, flags = 0)
52
+ @read_buffer ||= +''
53
+ loop do
54
+ result = recvfrom_nonblock(maxlen, flags, @read_buffer, **NO_EXCEPTION)
55
+ case result
56
+ when nil then raise IOError
57
+ when :wait_readable then Thread.current.agent.wait_io(self, false)
58
+ else
59
+ return result
60
+ end
61
+ end
62
+ end
63
+
64
+ ZERO_LINGER = [0, 0].pack('ii').freeze
65
+
66
+ def dont_linger
67
+ setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, ZERO_LINGER)
68
+ end
69
+
70
+ def no_delay
71
+ setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
72
+ end
73
+
74
+ def reuse_addr
75
+ setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
76
+ end
77
+
78
+ class << self
79
+ alias_method :orig_getaddrinfo, :getaddrinfo
80
+ def getaddrinfo(*args)
81
+ Polyphony::ThreadPool.process { orig_getaddrinfo(*args) }
82
+ end
83
+ end
84
+ end
85
+
86
+ # Overide stock TCPSocket code by encapsulating a Socket instance
87
+ class ::TCPSocket
88
+ NO_EXCEPTION = { exception: false }.freeze
89
+
90
+ attr_reader :io
91
+
92
+ def initialize(remote_host, remote_port, local_host = nil, local_port = nil)
93
+ @io = Socket.new Socket::AF_INET, Socket::SOCK_STREAM
94
+ if local_host && local_port
95
+ addr = Addrinfo.tcp(local_host, local_port)
96
+ @io.bind(addr)
97
+ end
98
+
99
+ return unless remote_host && remote_port
100
+
101
+ addr = Addrinfo.tcp(remote_host, remote_port)
102
+ @io.connect(addr)
103
+ end
104
+
105
+ alias_method :orig_close, :close
106
+ def close
107
+ @io ? @io.close : orig_close
108
+ end
109
+
110
+ alias_method :orig_setsockopt, :setsockopt
111
+ def setsockopt(*args)
112
+ @io ? @io.setsockopt(*args) : orig_setsockopt(*args)
113
+ end
114
+
115
+ alias_method :orig_closed?, :closed?
116
+ def closed?
117
+ @io ? @io.closed? : orig_closed?
118
+ end
119
+
120
+ def dont_linger
121
+ setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_LINGER, ::Socket::ZERO_LINGER)
122
+ end
123
+
124
+ def no_delay
125
+ setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
126
+ end
127
+
128
+ def reuse_addr
129
+ setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1)
130
+ end
131
+ end
132
+
133
+ # Override stock TCPServer code by encapsulating a Socket instance.
134
+ class ::TCPServer
135
+ def initialize(hostname = nil, port = 0)
136
+ @io = Socket.new Socket::AF_INET, Socket::SOCK_STREAM
137
+ @io.bind(Addrinfo.tcp(hostname, port))
138
+ @io.listen(0)
139
+ end
140
+
141
+ alias_method :orig_accept, :accept
142
+ def accept
143
+ @io.accept
144
+ end
145
+
146
+ alias_method :orig_close, :close
147
+ def close
148
+ @io.close
149
+ end
150
+ end