polyphony 0.98 → 0.99.1
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.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -1
- data/.rubocop.yml +3 -3
- data/.yardopts +30 -0
- data/CHANGELOG.md +11 -0
- data/LICENSE +1 -1
- data/README.md +63 -29
- data/Rakefile +1 -5
- data/TODO.md +0 -4
- data/docs/{main-concepts/concurrency.md → concurrency.md} +2 -9
- data/docs/{main-concepts/design-principles.md → design-principles.md} +3 -9
- data/docs/{main-concepts/exception-handling.md → exception-handling.md} +2 -9
- data/docs/{main-concepts/extending.md → extending.md} +2 -9
- data/docs/faq.md +3 -16
- data/docs/{main-concepts/fiber-scheduling.md → fiber-scheduling.md} +1 -9
- data/docs/link_rewriter.rb +16 -0
- data/docs/{getting-started/overview.md → overview.md} +1 -30
- data/docs/{getting-started/tutorial.md → tutorial.md} +3 -28
- data/docs/{_posts/2020-07-26-polyphony-0.44.md → whats-new.md} +3 -1
- data/examples/adapters/redis_client.rb +3 -2
- data/examples/io/echo_server.rb +1 -1
- data/examples/io/echo_server_plain_ruby.rb +26 -0
- data/examples/io/https_server_sni_2.rb +14 -8
- data/ext/polyphony/backend_io_uring.c +154 -9
- data/ext/polyphony/backend_io_uring_context.c +21 -12
- data/ext/polyphony/backend_io_uring_context.h +12 -7
- data/ext/polyphony/backend_libev.c +1 -1
- data/ext/polyphony/extconf.rb +25 -8
- data/ext/polyphony/fiber.c +79 -2
- data/ext/polyphony/io_extensions.c +53 -0
- data/ext/polyphony/libev.h +0 -2
- data/ext/polyphony/pipe.c +42 -2
- data/ext/polyphony/polyphony.c +345 -31
- data/ext/polyphony/polyphony.h +9 -2
- data/ext/polyphony/queue.c +181 -0
- data/ext/polyphony/ring_buffer.c +0 -1
- data/ext/polyphony/runqueue.c +8 -1
- data/ext/polyphony/runqueue_ring_buffer.c +13 -0
- data/ext/polyphony/runqueue_ring_buffer.h +2 -1
- data/ext/polyphony/socket_extensions.c +6 -0
- data/ext/polyphony/thread.c +34 -2
- data/lib/polyphony/adapters/process.rb +11 -1
- data/lib/polyphony/adapters/sequel.rb +1 -1
- data/lib/polyphony/core/channel.rb +2 -0
- data/lib/polyphony/core/debug.rb +1 -1
- data/lib/polyphony/core/global_api.rb +25 -24
- data/lib/polyphony/core/resource_pool.rb +7 -6
- data/lib/polyphony/core/sync.rb +55 -2
- data/lib/polyphony/core/thread_pool.rb +3 -3
- data/lib/polyphony/core/timer.rb +8 -8
- data/lib/polyphony/extensions/exception.rb +2 -0
- data/lib/polyphony/extensions/fiber.rb +15 -13
- data/lib/polyphony/extensions/io.rb +161 -16
- data/lib/polyphony/extensions/kernel.rb +20 -2
- data/lib/polyphony/extensions/openssl.rb +101 -12
- data/lib/polyphony/extensions/pipe.rb +103 -7
- data/lib/polyphony/extensions/process.rb +13 -1
- data/lib/polyphony/extensions/socket.rb +93 -27
- data/lib/polyphony/extensions/thread.rb +9 -1
- data/lib/polyphony/extensions/timeout.rb +1 -1
- data/lib/polyphony/version.rb +2 -1
- data/lib/polyphony.rb +27 -7
- data/polyphony.gemspec +1 -8
- data/test/stress.rb +1 -1
- data/test/test_global_api.rb +45 -7
- data/test/test_io.rb +6 -7
- data/test/test_socket.rb +157 -0
- data/test/test_sync.rb +42 -1
- data/test/test_timer.rb +5 -5
- data/vendor/liburing/.github/workflows/build.yml +7 -16
- data/vendor/liburing/.gitignore +5 -0
- data/vendor/liburing/CHANGELOG +23 -1
- data/vendor/liburing/Makefile +4 -3
- data/vendor/liburing/Makefile.common +1 -0
- data/vendor/liburing/README +48 -0
- data/vendor/liburing/configure +76 -6
- data/vendor/liburing/debian/changelog +11 -0
- data/vendor/liburing/debian/control +7 -16
- data/vendor/liburing/debian/liburing-dev.manpages +3 -6
- data/vendor/liburing/debian/liburing2.install +1 -0
- data/vendor/liburing/debian/liburing2.symbols +56 -0
- data/vendor/liburing/debian/rules +15 -68
- data/vendor/liburing/examples/Makefile +4 -0
- data/vendor/liburing/examples/io_uring-close-test.c +123 -0
- data/vendor/liburing/examples/io_uring-udp.c +1 -1
- data/vendor/liburing/examples/send-zerocopy.c +315 -56
- data/vendor/liburing/examples/ucontext-cp.c +2 -17
- data/vendor/liburing/liburing-ffi.pc.in +12 -0
- data/vendor/liburing/liburing.pc.in +1 -1
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/make-debs.sh +3 -3
- data/vendor/liburing/man/IO_URING_CHECK_VERSION.3 +1 -0
- data/vendor/liburing/man/IO_URING_VERSION_MAJOR.3 +1 -0
- data/vendor/liburing/man/IO_URING_VERSION_MINOR.3 +1 -0
- data/vendor/liburing/man/io_uring_buf_ring_add.3 +6 -6
- data/vendor/liburing/man/io_uring_check_version.3 +72 -0
- data/vendor/liburing/man/io_uring_close_ring_fd.3 +43 -0
- data/vendor/liburing/man/io_uring_major_version.3 +1 -0
- data/vendor/liburing/man/io_uring_minor_version.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_accept.3 +1 -1
- data/vendor/liburing/man/io_uring_prep_fgetxattr.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_fsetxattr.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_getxattr.3 +61 -0
- data/vendor/liburing/man/io_uring_prep_link_timeout.3 +94 -0
- data/vendor/liburing/man/io_uring_prep_msg_ring.3 +22 -2
- data/vendor/liburing/man/io_uring_prep_msg_ring_cqe_flags.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_poll_add.3 +1 -1
- data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +18 -9
- data/vendor/liburing/man/io_uring_prep_readv.3 +3 -3
- data/vendor/liburing/man/io_uring_prep_readv2.3 +3 -3
- data/vendor/liburing/man/io_uring_prep_recv.3 +5 -5
- data/vendor/liburing/man/io_uring_prep_recvmsg.3 +4 -4
- data/vendor/liburing/man/io_uring_prep_send.3 +9 -0
- data/vendor/liburing/man/io_uring_prep_send_set_addr.3 +38 -0
- data/vendor/liburing/man/io_uring_prep_send_zc.3 +39 -7
- data/vendor/liburing/man/io_uring_prep_send_zc_fixed.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_sendmsg.3 +20 -0
- data/vendor/liburing/man/io_uring_prep_sendmsg_zc.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_setxattr.3 +64 -0
- data/vendor/liburing/man/io_uring_prep_splice.3 +40 -0
- data/vendor/liburing/man/io_uring_prep_writev.3 +2 -2
- data/vendor/liburing/man/io_uring_prep_writev2.3 +2 -2
- data/vendor/liburing/man/io_uring_recvmsg_out.3 +13 -9
- data/vendor/liburing/man/io_uring_register.2 +15 -9
- data/vendor/liburing/man/io_uring_register_buf_ring.3 +4 -4
- data/vendor/liburing/man/io_uring_register_buffers.3 +49 -6
- data/vendor/liburing/man/io_uring_register_buffers_sparse.3 +1 -0
- data/vendor/liburing/man/io_uring_register_buffers_tags.3 +1 -0
- data/vendor/liburing/man/io_uring_register_buffers_update_tag.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files.3 +60 -5
- data/vendor/liburing/man/io_uring_register_files_tags.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files_update.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files_update_tag.3 +1 -0
- data/vendor/liburing/man/io_uring_setup.2 +31 -2
- data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +1 -1
- data/vendor/liburing/src/Makefile +25 -3
- data/vendor/liburing/src/ffi.c +15 -0
- data/vendor/liburing/src/include/liburing/io_uring.h +30 -7
- data/vendor/liburing/src/include/liburing.h +190 -148
- data/vendor/liburing/src/int_flags.h +1 -0
- data/vendor/liburing/src/lib.h +5 -16
- data/vendor/liburing/src/liburing-ffi.map +172 -0
- data/vendor/liburing/src/liburing.map +11 -0
- data/vendor/liburing/src/nolibc.c +9 -2
- data/vendor/liburing/src/queue.c +2 -2
- data/vendor/liburing/src/register.c +66 -96
- data/vendor/liburing/src/setup.c +5 -4
- data/vendor/liburing/src/version.c +21 -0
- data/vendor/liburing/test/232c93d07b74.c +3 -3
- data/vendor/liburing/test/35fa71a030ca.c +3 -3
- data/vendor/liburing/test/500f9fbadef8.c +2 -0
- data/vendor/liburing/test/917257daa0fe.c +1 -1
- data/vendor/liburing/test/Makefile +27 -7
- data/vendor/liburing/test/a0908ae19763.c +2 -2
- data/vendor/liburing/test/a4c0b3decb33.c +2 -2
- data/vendor/liburing/test/accept-link.c +4 -4
- data/vendor/liburing/test/accept-reuse.c +5 -7
- data/vendor/liburing/test/accept.c +34 -31
- data/vendor/liburing/test/b19062a56726.c +1 -1
- data/vendor/liburing/test/buf-ring.c +58 -4
- data/vendor/liburing/test/ce593a6c480a.c +2 -2
- data/vendor/liburing/test/close-opath.c +2 -1
- data/vendor/liburing/test/connect.c +8 -0
- data/vendor/liburing/test/cq-overflow.c +14 -8
- data/vendor/liburing/test/d4ae271dfaae.c +1 -1
- data/vendor/liburing/test/defer-taskrun.c +64 -9
- data/vendor/liburing/test/defer.c +1 -1
- data/vendor/liburing/test/double-poll-crash.c +3 -3
- data/vendor/liburing/test/eeed8b54e0df.c +8 -3
- data/vendor/liburing/test/eploop.c +74 -0
- data/vendor/liburing/test/eventfd-ring.c +1 -1
- data/vendor/liburing/test/eventfd.c +1 -1
- data/vendor/liburing/test/evloop.c +73 -0
- data/vendor/liburing/test/exit-no-cleanup.c +1 -1
- data/vendor/liburing/test/fadvise.c +1 -1
- data/vendor/liburing/test/fc2a85cb02ef.c +3 -3
- data/vendor/liburing/test/fd-pass.c +35 -16
- data/vendor/liburing/test/file-register.c +61 -0
- data/vendor/liburing/test/file-verify.c +2 -2
- data/vendor/liburing/test/files-exit-hang-timeout.c +2 -2
- data/vendor/liburing/test/fixed-link.c +1 -1
- data/vendor/liburing/test/fsnotify.c +118 -0
- data/vendor/liburing/test/hardlink.c +1 -1
- data/vendor/liburing/test/helpers.c +54 -2
- data/vendor/liburing/test/helpers.h +4 -0
- data/vendor/liburing/test/io-cancel.c +3 -1
- data/vendor/liburing/test/io_uring_passthrough.c +39 -8
- data/vendor/liburing/test/io_uring_setup.c +3 -80
- data/vendor/liburing/test/iopoll-overflow.c +118 -0
- data/vendor/liburing/test/iopoll.c +90 -4
- data/vendor/liburing/test/lfs-openat-write.c +7 -9
- data/vendor/liburing/test/lfs-openat.c +6 -8
- data/vendor/liburing/test/link_drain.c +31 -5
- data/vendor/liburing/test/madvise.c +1 -1
- data/vendor/liburing/test/msg-ring-flags.c +192 -0
- data/vendor/liburing/test/msg-ring-overflow.c +159 -0
- data/vendor/liburing/test/msg-ring.c +173 -13
- data/vendor/liburing/test/multicqes_drain.c +22 -19
- data/vendor/liburing/test/nvme.h +4 -3
- data/vendor/liburing/test/pipe-bug.c +95 -0
- data/vendor/liburing/test/poll-link.c +3 -3
- data/vendor/liburing/test/poll-many.c +41 -19
- data/vendor/liburing/test/poll-mshot-overflow.c +105 -2
- data/vendor/liburing/test/poll-race-mshot.c +292 -0
- data/vendor/liburing/test/poll-race.c +105 -0
- data/vendor/liburing/test/poll.c +244 -26
- data/vendor/liburing/test/pollfree.c +5 -5
- data/vendor/liburing/test/read-before-exit.c +20 -3
- data/vendor/liburing/test/read-write.c +2 -0
- data/vendor/liburing/test/recv-multishot.c +96 -3
- data/vendor/liburing/test/reg-reg-ring.c +90 -0
- data/vendor/liburing/test/rename.c +1 -1
- data/vendor/liburing/test/ring-leak.c +0 -1
- data/vendor/liburing/test/ring-leak2.c +1 -1
- data/vendor/liburing/test/ringbuf-read.c +10 -6
- data/vendor/liburing/test/send-zerocopy.c +273 -103
- data/vendor/liburing/test/send_recv.c +7 -4
- data/vendor/liburing/test/sendmsg_fs_cve.c +2 -2
- data/vendor/liburing/test/single-issuer.c +7 -9
- data/vendor/liburing/test/skip-cqe.c +3 -4
- data/vendor/liburing/test/socket.c +0 -1
- data/vendor/liburing/test/sq-poll-dup.c +10 -3
- data/vendor/liburing/test/sq-poll-kthread.c +1 -1
- data/vendor/liburing/test/sq-poll-share.c +3 -2
- data/vendor/liburing/test/sqpoll-cancel-hang.c +17 -6
- data/vendor/liburing/test/sqpoll-disable-exit.c +4 -4
- data/vendor/liburing/test/symlink.c +2 -1
- data/vendor/liburing/test/test.h +2 -1
- data/vendor/liburing/test/timeout-new.c +11 -7
- data/vendor/liburing/test/timeout.c +1 -2
- data/vendor/liburing/test/unlink.c +1 -1
- data/vendor/liburing/test/version.c +25 -0
- data/vendor/liburing/test/wakeup-hang.c +1 -1
- data/vendor/liburing/test/xattr.c +8 -4
- metadata +57 -44
- data/docs/_config.yml +0 -64
- data/docs/_includes/head.html +0 -40
- data/docs/_includes/title.html +0 -1
- data/docs/_sass/custom/custom.scss +0 -10
- data/docs/_sass/overrides.scss +0 -0
- data/docs/api-reference/exception.md +0 -31
- data/docs/api-reference/fiber.md +0 -425
- data/docs/api-reference/index.md +0 -9
- data/docs/api-reference/io.md +0 -36
- data/docs/api-reference/object.md +0 -99
- data/docs/api-reference/polyphony-baseexception.md +0 -33
- data/docs/api-reference/polyphony-cancel.md +0 -26
- data/docs/api-reference/polyphony-moveon.md +0 -24
- data/docs/api-reference/polyphony-net.md +0 -20
- data/docs/api-reference/polyphony-process.md +0 -28
- data/docs/api-reference/polyphony-resourcepool.md +0 -59
- data/docs/api-reference/polyphony-restart.md +0 -18
- data/docs/api-reference/polyphony-terminate.md +0 -18
- data/docs/api-reference/polyphony-threadpool.md +0 -67
- data/docs/api-reference/polyphony-throttler.md +0 -77
- data/docs/api-reference/polyphony.md +0 -36
- data/docs/api-reference/thread.md +0 -88
- data/docs/favicon.ico +0 -0
- data/docs/getting-started/index.md +0 -10
- data/docs/getting-started/installing.md +0 -34
- data/vendor/liburing/debian/compat +0 -1
- data/vendor/liburing/debian/liburing1-udeb.install +0 -1
- data/vendor/liburing/debian/liburing1.install +0 -1
- data/vendor/liburing/debian/liburing1.symbols +0 -32
- /data/{docs/assets/img → assets}/echo-fibers.svg +0 -0
- /data/{docs → assets}/polyphony-logo.png +0 -0
- /data/{docs/assets/img → assets}/sleeping-fiber.svg +0 -0
|
@@ -8,7 +8,7 @@ module Polyphony
|
|
|
8
8
|
# Initializes a new resource pool.
|
|
9
9
|
#
|
|
10
10
|
# @param opts [Hash] options
|
|
11
|
-
# @
|
|
11
|
+
# @yield [] allocator block
|
|
12
12
|
def initialize(opts, &block)
|
|
13
13
|
@allocator = block
|
|
14
14
|
@limit = opts[:limit] || 4
|
|
@@ -36,7 +36,7 @@ module Polyphony
|
|
|
36
36
|
# db.query(sql).to_a
|
|
37
37
|
# end
|
|
38
38
|
#
|
|
39
|
-
# @
|
|
39
|
+
# @yield [any] code to run
|
|
40
40
|
# @return [any] return value of block
|
|
41
41
|
def acquire(&block)
|
|
42
42
|
fiber = Fiber.current
|
|
@@ -54,13 +54,14 @@ module Polyphony
|
|
|
54
54
|
# }
|
|
55
55
|
#
|
|
56
56
|
# @param sym [Symbol] method name
|
|
57
|
-
# @param
|
|
58
|
-
# @
|
|
57
|
+
# @param args [Array<any>] method arguments
|
|
58
|
+
# @yield [any] block passed to method
|
|
59
|
+
# @return [any] result of method call
|
|
59
60
|
def method_missing(sym, *args, &block)
|
|
60
61
|
acquire { |r| r.send(sym, *args, &block) }
|
|
61
62
|
end
|
|
62
63
|
|
|
63
|
-
#
|
|
64
|
+
# @!visibility private
|
|
64
65
|
def respond_to_missing?(*_args)
|
|
65
66
|
true
|
|
66
67
|
end
|
|
@@ -87,7 +88,7 @@ module Polyphony
|
|
|
87
88
|
# Acquires a resource from stock, yielding it to the given block.
|
|
88
89
|
#
|
|
89
90
|
# @param fiber [Fiber] the fiber the resource will be associated with
|
|
90
|
-
# @
|
|
91
|
+
# @yield [any] given block
|
|
91
92
|
# @return [any] return value of block
|
|
92
93
|
def acquire_from_stock(fiber)
|
|
93
94
|
add_to_stock if (@stock.empty? || @stock.pending?) && @size < @limit
|
data/lib/polyphony/core/sync.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Polyphony
|
|
|
17
17
|
# This method is re-entrant. Recursive calls from the given block will not
|
|
18
18
|
# block.
|
|
19
19
|
#
|
|
20
|
-
# @
|
|
20
|
+
# @yield [] code to run
|
|
21
21
|
# @return [any] return value of block
|
|
22
22
|
def synchronize(&block)
|
|
23
23
|
return yield if @holding_fiber == Fiber.current
|
|
@@ -58,6 +58,58 @@ module Polyphony
|
|
|
58
58
|
@holding_fiber
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
# Obtains a lock. Raises `ThreadError` if mutex is locked by the current
|
|
62
|
+
# thread.
|
|
63
|
+
#
|
|
64
|
+
# @return [Mutex] self
|
|
65
|
+
def lock
|
|
66
|
+
raise ThreadError if owned?
|
|
67
|
+
|
|
68
|
+
@token = @store.shift
|
|
69
|
+
@holding_fiber = Fiber.current
|
|
70
|
+
self
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Releases the lock. Raises `ThreadError` if mutex is not locked by the
|
|
74
|
+
# current thread.
|
|
75
|
+
#
|
|
76
|
+
# @return [Mutex] self
|
|
77
|
+
def unlock
|
|
78
|
+
raise ThreadError if !owned?
|
|
79
|
+
|
|
80
|
+
@holding_fiber = nil
|
|
81
|
+
@store << @token if @token
|
|
82
|
+
@token = nil
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Attempts to obtain the lock and returns immediately. Returns `true` if the
|
|
86
|
+
# lock was granted.
|
|
87
|
+
#
|
|
88
|
+
# @return [true, false]
|
|
89
|
+
def try_lock
|
|
90
|
+
return false if @holding_fiber
|
|
91
|
+
|
|
92
|
+
@token = @store.shift
|
|
93
|
+
@holding_fiber = Fiber.current
|
|
94
|
+
true
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Releases the lock and sleeps timeout seconds if it is given and non-nil or
|
|
98
|
+
# forever. Raises `ThreadError` if mutex wasn’t locked by the current
|
|
99
|
+
# thread.
|
|
100
|
+
#
|
|
101
|
+
# @param timeout [nil, Number] sleep timeout
|
|
102
|
+
# @return [Number] slept time in seconds
|
|
103
|
+
def sleep(timeout = nil)
|
|
104
|
+
unlock
|
|
105
|
+
t0 = Time.now
|
|
106
|
+
Kernel.sleep(timeout)
|
|
107
|
+
t1 = Time.now
|
|
108
|
+
lock
|
|
109
|
+
|
|
110
|
+
return t1 - t0
|
|
111
|
+
end
|
|
112
|
+
|
|
61
113
|
private
|
|
62
114
|
|
|
63
115
|
# Helper method for performing a `#synchronize` when not currently holding
|
|
@@ -72,6 +124,7 @@ module Polyphony
|
|
|
72
124
|
ensure
|
|
73
125
|
@holding_fiber = nil
|
|
74
126
|
@store << @token if @token
|
|
127
|
+
@token = nil
|
|
75
128
|
end
|
|
76
129
|
end
|
|
77
130
|
end
|
|
@@ -87,7 +140,7 @@ module Polyphony
|
|
|
87
140
|
# Waits for the condition variable to be signalled.
|
|
88
141
|
#
|
|
89
142
|
# @param mutex [Polyphony::Mutex] mutex to release while waiting for signal
|
|
90
|
-
# @param
|
|
143
|
+
# @param _timeout [Number, nil] timeout in seconds (currently not implemented)
|
|
91
144
|
# @return [void]
|
|
92
145
|
def wait(mutex, _timeout = nil)
|
|
93
146
|
mutex.conditional_release
|
|
@@ -12,7 +12,7 @@ module Polyphony
|
|
|
12
12
|
|
|
13
13
|
# Runs the given block on an available thread from the default thread pool.
|
|
14
14
|
#
|
|
15
|
-
# @
|
|
15
|
+
# @yield [] given block
|
|
16
16
|
# @return [any] return value of given block
|
|
17
17
|
def self.process(&block)
|
|
18
18
|
@default_pool ||= new
|
|
@@ -41,7 +41,7 @@ module Polyphony
|
|
|
41
41
|
|
|
42
42
|
# Runs the given block on an available thread from the pool.
|
|
43
43
|
#
|
|
44
|
-
# @
|
|
44
|
+
# @yield [] given block
|
|
45
45
|
# @return [any] return value of block
|
|
46
46
|
def process(&block)
|
|
47
47
|
setup unless @task_queue
|
|
@@ -55,7 +55,7 @@ module Polyphony
|
|
|
55
55
|
# method does not block. The task will be performed once a thread becomes
|
|
56
56
|
# available.
|
|
57
57
|
#
|
|
58
|
-
# @
|
|
58
|
+
# @yield [] given block
|
|
59
59
|
# @return [Polyphony::ThreadPool] self
|
|
60
60
|
def cast(&block)
|
|
61
61
|
setup unless @task_queue
|
data/lib/polyphony/core/timer.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Polyphony
|
|
|
11
11
|
# Initializes a new timer with the given resolution.
|
|
12
12
|
#
|
|
13
13
|
# @param tag [any] tag to use for the timer's fiber
|
|
14
|
-
# @param resolution
|
|
14
|
+
# @param resolution [Number] timer granularity in seconds or fractions thereof
|
|
15
15
|
def initialize(tag = nil, resolution:)
|
|
16
16
|
@fiber = spin_loop(tag, interval: resolution) { update }
|
|
17
17
|
@timeouts = {}
|
|
@@ -43,8 +43,8 @@ module Polyphony
|
|
|
43
43
|
# Spins up a fiber that will run the given block after sleeping for the
|
|
44
44
|
# given delay.
|
|
45
45
|
#
|
|
46
|
-
# @param
|
|
47
|
-
# @
|
|
46
|
+
# @param interval [Number] delay in seconds before running the given block
|
|
47
|
+
# @yield [] block to run
|
|
48
48
|
# @return [Fiber] spun fiber
|
|
49
49
|
def after(interval, &block)
|
|
50
50
|
spin do
|
|
@@ -57,7 +57,7 @@ module Polyphony
|
|
|
57
57
|
# consecutive iterations.
|
|
58
58
|
#
|
|
59
59
|
# @param interval [Number] interval between consecutive iterations in seconds
|
|
60
|
-
# @
|
|
60
|
+
# @yield [] block to run
|
|
61
61
|
# @return [void]
|
|
62
62
|
def every(interval)
|
|
63
63
|
fiber = Fiber.current
|
|
@@ -109,8 +109,8 @@ module Polyphony
|
|
|
109
109
|
# end
|
|
110
110
|
#
|
|
111
111
|
# @param interval [Number] timout in seconds
|
|
112
|
-
# @param with_exception
|
|
113
|
-
# @
|
|
112
|
+
# @param with_exception [Class, Exception] exception or exception class
|
|
113
|
+
# @yield [Canceller] block to execute
|
|
114
114
|
# @return [any] block's return value
|
|
115
115
|
def cancel_after(interval, with_exception: Polyphony::Cancel)
|
|
116
116
|
fiber = Fiber.current
|
|
@@ -163,8 +163,8 @@ module Polyphony
|
|
|
163
163
|
# end
|
|
164
164
|
#
|
|
165
165
|
# @param interval [Number] timout in seconds
|
|
166
|
-
# @param with_value
|
|
167
|
-
# @
|
|
166
|
+
# @param with_value [any] return value in case of timeout
|
|
167
|
+
# @yield [Fiber] block to execute
|
|
168
168
|
# @return [any] block's return value
|
|
169
169
|
def move_on_after(interval, with_value: nil)
|
|
170
170
|
fiber = Fiber.current
|
|
@@ -18,6 +18,7 @@ class ::Exception
|
|
|
18
18
|
# Set to the fiber from which the exception was raised.
|
|
19
19
|
attr_accessor :raising_fiber
|
|
20
20
|
|
|
21
|
+
# @!visibility private
|
|
21
22
|
alias_method :orig_initialize, :initialize
|
|
22
23
|
|
|
23
24
|
# Initializes the exception with the given arguments.
|
|
@@ -26,6 +27,7 @@ class ::Exception
|
|
|
26
27
|
orig_initialize(*args)
|
|
27
28
|
end
|
|
28
29
|
|
|
30
|
+
# @!visibility private
|
|
29
31
|
alias_method :orig_backtrace, :backtrace
|
|
30
32
|
|
|
31
33
|
# Returns the backtrace for the exception. If
|
|
@@ -116,7 +116,7 @@ module Polyphony
|
|
|
116
116
|
# operation will be resumed. This API is experimental and might be removed
|
|
117
117
|
# in the future.
|
|
118
118
|
#
|
|
119
|
-
# @
|
|
119
|
+
# @yield [any] given block
|
|
120
120
|
# @return [Fiber] self
|
|
121
121
|
def interject(&block)
|
|
122
122
|
raise Polyphony::Interjection.new(block)
|
|
@@ -132,7 +132,7 @@ module Polyphony
|
|
|
132
132
|
|
|
133
133
|
private
|
|
134
134
|
|
|
135
|
-
#
|
|
135
|
+
# @!visibility private
|
|
136
136
|
def error_from_raise_args(args)
|
|
137
137
|
case (arg = args.shift)
|
|
138
138
|
when String then RuntimeError.new(arg)
|
|
@@ -171,10 +171,11 @@ module Polyphony
|
|
|
171
171
|
#
|
|
172
172
|
# This method blocks indefinitely.
|
|
173
173
|
#
|
|
174
|
-
# @param
|
|
175
|
-
# @
|
|
176
|
-
# @
|
|
177
|
-
# @
|
|
174
|
+
# @param fibers [Array<Fiber>] fibers to supervise
|
|
175
|
+
# @option opts [Proc, nil] :on_done proc to call when a supervised fiber is terminated
|
|
176
|
+
# @option opts [Proc, nil] :on_error proc to call when a supervised fiber is terminated with an exception
|
|
177
|
+
# @option opts [:always, :on_error, nil] :restart whether to restart terminated fibers
|
|
178
|
+
# @yield [] supervisor block
|
|
178
179
|
# @return [void]
|
|
179
180
|
def supervise(*fibers, **opts, &block)
|
|
180
181
|
block ||= supervise_opts_to_block(opts)
|
|
@@ -198,7 +199,7 @@ module Polyphony
|
|
|
198
199
|
|
|
199
200
|
private
|
|
200
201
|
|
|
201
|
-
#
|
|
202
|
+
# @!visibility private
|
|
202
203
|
def supervise_opts_to_block(opts)
|
|
203
204
|
block = opts[:on_done] || opts[:on_error]
|
|
204
205
|
restart = opts[:restart]
|
|
@@ -228,7 +229,7 @@ module Polyphony
|
|
|
228
229
|
# terminates with an uncaught exception, `Fiber.await` will await all the
|
|
229
230
|
# other fibers to terminate, then reraise the exception.
|
|
230
231
|
#
|
|
231
|
-
# @param
|
|
232
|
+
# @param fibers [Array<Fiber>] fibers to wait for
|
|
232
233
|
# @return [Array<any>] return values of given fibers
|
|
233
234
|
def await(*fibers)
|
|
234
235
|
return [] if fibers.empty?
|
|
@@ -267,7 +268,7 @@ module Polyphony
|
|
|
267
268
|
# array containing the first terminated fiber and its return value. If an
|
|
268
269
|
# exception occurs in one of the given fibers, it will be reraised.
|
|
269
270
|
#
|
|
270
|
-
# @param
|
|
271
|
+
# @param fibers [Array<Fiber>] Fibers to wait for
|
|
271
272
|
# @return [Array] Array containing the first terminated fiber and its return value
|
|
272
273
|
def select(*fibers)
|
|
273
274
|
return nil if fibers.empty?
|
|
@@ -301,7 +302,7 @@ module Polyphony
|
|
|
301
302
|
# also be scheduled with priority. This method is mainly used trapping
|
|
302
303
|
# signals (see also the patched `Kernel#trap`)
|
|
303
304
|
#
|
|
304
|
-
# @
|
|
305
|
+
# @yield [] given block
|
|
305
306
|
# @return [void]
|
|
306
307
|
def schedule_priority_oob_fiber(&block)
|
|
307
308
|
oob_fiber = Fiber.new do
|
|
@@ -322,7 +323,7 @@ module Polyphony
|
|
|
322
323
|
|
|
323
324
|
private
|
|
324
325
|
|
|
325
|
-
#
|
|
326
|
+
# @!visibility private
|
|
326
327
|
def prepare_oob_fiber(fiber, block)
|
|
327
328
|
fiber.oob = true
|
|
328
329
|
fiber.tag = :oob
|
|
@@ -348,7 +349,7 @@ module Polyphony
|
|
|
348
349
|
#
|
|
349
350
|
# @param tag [any] child fiber's tag
|
|
350
351
|
# @param orig_caller [Array<String>] caller to set for fiber
|
|
351
|
-
# @
|
|
352
|
+
# @yield [any] child fiber's block
|
|
352
353
|
# @return [Fiber] child fiber
|
|
353
354
|
def spin(tag = nil, orig_caller = Kernel.caller, &block)
|
|
354
355
|
f = Fiber.new { |v| f.run(v) }
|
|
@@ -456,10 +457,11 @@ module Polyphony
|
|
|
456
457
|
|
|
457
458
|
# Removes a child fiber reference. Used internally.
|
|
458
459
|
#
|
|
459
|
-
# @param
|
|
460
|
+
# @param child_fiber [Fiber] child fiber to be removed
|
|
460
461
|
# @return [Fiber] self
|
|
461
462
|
def remove_child(child_fiber)
|
|
462
463
|
@children.delete(child_fiber) if @children
|
|
464
|
+
self
|
|
463
465
|
end
|
|
464
466
|
end
|
|
465
467
|
|
|
@@ -5,9 +5,10 @@ require 'open3'
|
|
|
5
5
|
# IO extensions
|
|
6
6
|
class ::IO
|
|
7
7
|
class << self
|
|
8
|
+
# @!visibility private
|
|
8
9
|
alias_method :orig_binread, :binread
|
|
9
10
|
|
|
10
|
-
#
|
|
11
|
+
# @!visibility private
|
|
11
12
|
def binread(name, length = nil, offset = nil)
|
|
12
13
|
File.open(name, 'rb:ASCII-8BIT') do |f|
|
|
13
14
|
f.seek(offset) if offset
|
|
@@ -15,7 +16,10 @@ class ::IO
|
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
|
|
19
|
+
# @!visibility private
|
|
18
20
|
alias_method :orig_binwrite, :binwrite
|
|
21
|
+
|
|
22
|
+
# @!visibility private
|
|
19
23
|
def binwrite(name, string, offset = nil)
|
|
20
24
|
File.open(name, 'wb:ASCII-8BIT') do |f|
|
|
21
25
|
f.seek(offset) if offset
|
|
@@ -23,24 +27,27 @@ class ::IO
|
|
|
23
27
|
end
|
|
24
28
|
end
|
|
25
29
|
|
|
30
|
+
# @!visibility private
|
|
26
31
|
EMPTY_HASH = {}.freeze
|
|
27
32
|
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
#
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
# end
|
|
33
|
+
# @!visibility private
|
|
34
|
+
alias_method :orig_foreach, :foreach
|
|
35
|
+
|
|
36
|
+
# @!visibility private
|
|
37
|
+
def foreach(name, sep = $/, limit = nil, getline_args = EMPTY_HASH, &block)
|
|
38
|
+
if sep.is_a?(Integer)
|
|
39
|
+
sep = $/
|
|
40
|
+
limit = sep
|
|
41
|
+
end
|
|
42
|
+
File.open(name, 'r') do |f|
|
|
43
|
+
f.each_line(sep, limit, chomp: getline_args[:chomp], &block)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
42
46
|
|
|
47
|
+
# @!visibility private
|
|
43
48
|
alias_method :orig_read, :read
|
|
49
|
+
|
|
50
|
+
# @!visibility private
|
|
44
51
|
def read(name, length = nil, offset = nil, opt = EMPTY_HASH)
|
|
45
52
|
if length.is_a?(Hash)
|
|
46
53
|
opt = length
|
|
@@ -59,7 +66,10 @@ class ::IO
|
|
|
59
66
|
# end
|
|
60
67
|
# end
|
|
61
68
|
|
|
69
|
+
# @!visibility private
|
|
62
70
|
alias_method :orig_write, :write
|
|
71
|
+
|
|
72
|
+
# @!visibility private
|
|
63
73
|
def write(name, string, offset = nil, opt = EMPTY_HASH)
|
|
64
74
|
File.open(name, opt[:mode] || 'w') do |f|
|
|
65
75
|
f.seek(offset) if offset
|
|
@@ -67,22 +77,44 @@ class ::IO
|
|
|
67
77
|
end
|
|
68
78
|
end
|
|
69
79
|
|
|
80
|
+
# @!visibility private
|
|
70
81
|
alias_method :orig_popen, :popen
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# @!visibility private
|
|
71
85
|
def popen(cmd, mode = 'r')
|
|
72
86
|
return orig_popen(cmd, mode) unless block_given?
|
|
73
87
|
|
|
74
88
|
Open3.popen2(cmd) { |_i, o, _t| yield o }
|
|
75
89
|
end
|
|
76
90
|
|
|
91
|
+
# Splices from one IO to another IO. At least one of the IOs must be a pipe.
|
|
92
|
+
#
|
|
93
|
+
# @param src [IO, Polyphony::Pipe] source to splice from
|
|
94
|
+
# @param dest [IO, Polyphony::Pipe] destination to splice to
|
|
95
|
+
# @param maxlen [Integer] maximum bytes to splice
|
|
96
|
+
# @return [Integer] bytes spliced
|
|
77
97
|
def splice(src, dest, maxlen)
|
|
78
98
|
Polyphony.backend_splice(src, dest, maxlen)
|
|
79
99
|
end
|
|
80
100
|
|
|
81
101
|
if RUBY_PLATFORM =~ /linux/
|
|
102
|
+
# Creates a pipe and splices data between the two given IOs using the
|
|
103
|
+
# pipe, splicing until EOF.
|
|
104
|
+
#
|
|
105
|
+
# @param src [IO, Polyphony::Pipe] source to splice from
|
|
106
|
+
# @param dest [IO, Polyphony::Pipe] destination to splice to
|
|
107
|
+
# @return [Integer] total bytes spliced
|
|
82
108
|
def double_splice(src, dest)
|
|
83
109
|
Polyphony.backend_double_splice(src, dest)
|
|
84
110
|
end
|
|
85
111
|
|
|
112
|
+
# Tees data from the source to the desination.
|
|
113
|
+
#
|
|
114
|
+
# @param src [IO, Polyphony::Pipe] source to tee from
|
|
115
|
+
# @param dest [IO, Polyphony::Pipe] destination to tee to
|
|
116
|
+
# @param maxlen [Integer] maximum bytes to tee
|
|
117
|
+
# @return [Integer] total bytes teed
|
|
86
118
|
def tee(src, dest, maxlen)
|
|
87
119
|
Polyphony.backend_tee(src, dest, maxlen)
|
|
88
120
|
end
|
|
@@ -92,10 +124,12 @@ end
|
|
|
92
124
|
|
|
93
125
|
# IO instance method patches
|
|
94
126
|
class ::IO
|
|
127
|
+
# @!visibility private
|
|
95
128
|
def __read_method__
|
|
96
129
|
:backend_read
|
|
97
130
|
end
|
|
98
131
|
|
|
132
|
+
# @!visibility private
|
|
99
133
|
def __write_method__
|
|
100
134
|
:backend_write
|
|
101
135
|
end
|
|
@@ -114,13 +148,21 @@ class ::IO
|
|
|
114
148
|
# def each_codepoint
|
|
115
149
|
# end
|
|
116
150
|
|
|
151
|
+
# @!visibility private
|
|
117
152
|
alias_method :orig_getbyte, :getbyte
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# @!visibility private
|
|
118
156
|
def getbyte
|
|
119
157
|
char = getc
|
|
120
158
|
char ? char.getbyte(0) : nil
|
|
121
159
|
end
|
|
122
160
|
|
|
161
|
+
# @!visibility private
|
|
123
162
|
alias_method :orig_getc, :getc
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# @!visibility private
|
|
124
166
|
def getc
|
|
125
167
|
return @read_buffer.slice!(0) if @read_buffer && !@read_buffer.empty?
|
|
126
168
|
|
|
@@ -131,6 +173,7 @@ class ::IO
|
|
|
131
173
|
nil
|
|
132
174
|
end
|
|
133
175
|
|
|
176
|
+
# @!visibility private
|
|
134
177
|
def ungetc(c)
|
|
135
178
|
c = c.chr if c.is_a?(Integer)
|
|
136
179
|
if @read_buffer
|
|
@@ -141,7 +184,11 @@ class ::IO
|
|
|
141
184
|
end
|
|
142
185
|
alias_method :ungetbyte, :ungetc
|
|
143
186
|
|
|
187
|
+
# @!visibility private
|
|
144
188
|
alias_method :orig_read, :read
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
# @!visibility private
|
|
145
192
|
def read(len = nil, buf = nil, buf_pos = 0)
|
|
146
193
|
return '' if len == 0
|
|
147
194
|
|
|
@@ -158,7 +205,10 @@ class ::IO
|
|
|
158
205
|
already_read
|
|
159
206
|
end
|
|
160
207
|
|
|
208
|
+
# @!visibility private
|
|
161
209
|
alias_method :orig_readpartial, :read
|
|
210
|
+
|
|
211
|
+
# @!visibility private
|
|
162
212
|
def readpartial(len, str = +'', buffer_pos = 0, raise_on_eof = true)
|
|
163
213
|
result = Polyphony.backend_read(self, str, len, false, buffer_pos)
|
|
164
214
|
raise EOFError if !result && raise_on_eof
|
|
@@ -166,18 +216,27 @@ class ::IO
|
|
|
166
216
|
result
|
|
167
217
|
end
|
|
168
218
|
|
|
219
|
+
# @!visibility private
|
|
169
220
|
alias_method :orig_write, :write
|
|
221
|
+
|
|
222
|
+
# @!visibility private
|
|
170
223
|
def write(str, *args)
|
|
171
224
|
Polyphony.backend_write(self, str, *args)
|
|
172
225
|
end
|
|
173
226
|
|
|
227
|
+
# @!visibility private
|
|
174
228
|
alias_method :orig_write_chevron, :<<
|
|
229
|
+
|
|
230
|
+
# @!visibility private
|
|
175
231
|
def <<(str)
|
|
176
232
|
Polyphony.backend_write(self, str)
|
|
177
233
|
self
|
|
178
234
|
end
|
|
179
|
-
|
|
235
|
+
|
|
236
|
+
# @!visibility private
|
|
180
237
|
alias_method :orig_gets, :gets
|
|
238
|
+
|
|
239
|
+
# @!visibility private
|
|
181
240
|
def gets(sep = $/, _limit = nil, _chomp: nil)
|
|
182
241
|
if sep.is_a?(Integer)
|
|
183
242
|
sep = $/
|
|
@@ -198,6 +257,31 @@ class ::IO
|
|
|
198
257
|
return nil
|
|
199
258
|
end
|
|
200
259
|
|
|
260
|
+
# @!visibility private
|
|
261
|
+
def each_line(sep = $/, limit = nil, chomp: false)
|
|
262
|
+
if sep.is_a?(Integer)
|
|
263
|
+
limit = sep
|
|
264
|
+
sep = $/
|
|
265
|
+
end
|
|
266
|
+
sep_size = sep.bytesize
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@read_buffer ||= +''
|
|
270
|
+
|
|
271
|
+
while true
|
|
272
|
+
while (idx = @read_buffer.index(sep))
|
|
273
|
+
line = @read_buffer.slice!(0, idx + sep_size)
|
|
274
|
+
line = line.chomp if chomp
|
|
275
|
+
yield line
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
result = readpartial(8192, @read_buffer, -1)
|
|
279
|
+
return self if !result
|
|
280
|
+
end
|
|
281
|
+
rescue EOFError
|
|
282
|
+
return self
|
|
283
|
+
end
|
|
284
|
+
|
|
201
285
|
# def print(*args)
|
|
202
286
|
# end
|
|
203
287
|
|
|
@@ -207,10 +291,15 @@ class ::IO
|
|
|
207
291
|
# def putc(obj)
|
|
208
292
|
# end
|
|
209
293
|
|
|
294
|
+
# @!visibility private
|
|
210
295
|
LINEFEED = "\n"
|
|
296
|
+
# @!visibility private
|
|
211
297
|
LINEFEED_RE = /\n$/.freeze
|
|
212
298
|
|
|
299
|
+
# @!visibility private
|
|
213
300
|
alias_method :orig_puts, :puts
|
|
301
|
+
|
|
302
|
+
# @!visibility private
|
|
214
303
|
def puts(*args)
|
|
215
304
|
if args.empty?
|
|
216
305
|
write LINEFEED
|
|
@@ -245,24 +334,66 @@ class ::IO
|
|
|
245
334
|
# def readlines(sep = $/, limit = nil, chomp: nil)
|
|
246
335
|
# end
|
|
247
336
|
|
|
337
|
+
# @!visibility private
|
|
248
338
|
alias_method :orig_write_nonblock, :write_nonblock
|
|
339
|
+
|
|
340
|
+
# @!visibility private
|
|
249
341
|
def write_nonblock(string, _options = {})
|
|
250
342
|
write(string)
|
|
251
343
|
end
|
|
252
344
|
|
|
345
|
+
# @!visibility private
|
|
253
346
|
alias_method :orig_read_nonblock, :read_nonblock
|
|
347
|
+
|
|
348
|
+
# @!visibility private
|
|
254
349
|
def read_nonblock(maxlen, buf = nil, _options = nil)
|
|
255
350
|
buf ? readpartial(maxlen, buf) : readpartial(maxlen)
|
|
256
351
|
end
|
|
257
352
|
|
|
353
|
+
# call-seq:
|
|
354
|
+
# io.read_loop { |data| ... }
|
|
355
|
+
# io.read_loop(maxlen) { |data| ... }
|
|
356
|
+
#
|
|
357
|
+
# Reads up to `maxlen` bytes at a time in an infinite loop. Read data
|
|
358
|
+
# will be passed to the given block.
|
|
359
|
+
#
|
|
360
|
+
# @param maxlen [Integer] maximum bytes to receive
|
|
361
|
+
# @yield [String] handler block
|
|
362
|
+
# @return [void]
|
|
258
363
|
def read_loop(maxlen = 8192, &block)
|
|
259
364
|
Polyphony.backend_read_loop(self, maxlen, &block)
|
|
260
365
|
end
|
|
261
366
|
|
|
367
|
+
# call-seq:
|
|
368
|
+
# io.feed_loop(receiver, method)
|
|
369
|
+
# io.feed_loop(receiver, method) { |result| ... }
|
|
370
|
+
#
|
|
371
|
+
# Receives data from the io in an infinite loop, passing the data to the given
|
|
372
|
+
# receiver using the given method. If a block is given, the result of the
|
|
373
|
+
# method call to the receiver is passed to the block.
|
|
374
|
+
#
|
|
375
|
+
# This method can be used to feed data into parser objects. The following
|
|
376
|
+
# example shows how to feed data from a io directly into a MessagePack
|
|
377
|
+
# unpacker:
|
|
378
|
+
#
|
|
379
|
+
# unpacker = MessagePack::Unpacker.new
|
|
380
|
+
# buffer = []
|
|
381
|
+
# reader = spin do
|
|
382
|
+
# io.feed_loop(unpacker, :feed_each) { |msg| handle_msg(msg) }
|
|
383
|
+
# end
|
|
384
|
+
#
|
|
385
|
+
# @param receiver [any] receiver object
|
|
386
|
+
# @param method [Symbol] method to call
|
|
387
|
+
# @yield [any] block to handle result of method call to receiver
|
|
388
|
+
# @return [void]
|
|
262
389
|
def feed_loop(receiver, method = :call, &block)
|
|
263
390
|
Polyphony.backend_feed_loop(self, receiver, method, &block)
|
|
264
391
|
end
|
|
265
392
|
|
|
393
|
+
# Waits for the IO to become readable, with an optional timeout.
|
|
394
|
+
#
|
|
395
|
+
# @param timeout [Integer, nil] optional timeout in seconds.
|
|
396
|
+
# @return [IO] self
|
|
266
397
|
def wait_readable(timeout = nil)
|
|
267
398
|
return self if @read_buffer && @read_buffer.size > 0
|
|
268
399
|
|
|
@@ -277,6 +408,10 @@ class ::IO
|
|
|
277
408
|
end
|
|
278
409
|
end
|
|
279
410
|
|
|
411
|
+
# Waits for the IO to become writeable, with an optional timeout.
|
|
412
|
+
#
|
|
413
|
+
# @param timeout [Integer, nil] optional timeout in seconds.
|
|
414
|
+
# @return [IO] self
|
|
280
415
|
def wait_writable(timeout = nil)
|
|
281
416
|
if timeout
|
|
282
417
|
move_on_after(timeout) do
|
|
@@ -289,11 +424,21 @@ class ::IO
|
|
|
289
424
|
end
|
|
290
425
|
end
|
|
291
426
|
|
|
427
|
+
# Splices data from the given IO.
|
|
428
|
+
#
|
|
429
|
+
# @param src [IO, Polpyhony::Pipe] source to splice from
|
|
430
|
+
# @param maxlen [Integer] maximum bytes to splice
|
|
431
|
+
# @return [Integer] bytes spliced
|
|
292
432
|
def splice_from(src, maxlen)
|
|
293
433
|
Polyphony.backend_splice(src, self, maxlen)
|
|
294
434
|
end
|
|
295
435
|
|
|
296
436
|
if RUBY_PLATFORM =~ /linux/
|
|
437
|
+
# Tees data from the given IO.
|
|
438
|
+
#
|
|
439
|
+
# @param src [IO, Polpyhony::Pipe] source to tee from
|
|
440
|
+
# @param maxlen [Integer] maximum bytes to tee
|
|
441
|
+
# @return [Integer] bytes teed
|
|
297
442
|
def tee_from(src, maxlen)
|
|
298
443
|
Polyphony.backend_tee(src, self, maxlen)
|
|
299
444
|
end
|