polyphony 0.79 → 0.80
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/CHANGELOG.md +10 -0
- data/Gemfile.lock +2 -1
- data/examples/core/zlib_stream.rb +15 -0
- data/ext/polyphony/backend_common.c +2 -1
- data/ext/polyphony/backend_common.h +7 -2
- data/lib/polyphony/adapters/fs.rb +4 -0
- data/lib/polyphony/adapters/process.rb +14 -1
- data/lib/polyphony/adapters/redis.rb +28 -0
- data/lib/polyphony/adapters/sequel.rb +19 -1
- data/lib/polyphony/core/debug.rb +129 -72
- data/lib/polyphony/core/exceptions.rb +21 -6
- data/lib/polyphony/core/global_api.rb +228 -73
- data/lib/polyphony/core/resource_pool.rb +65 -20
- data/lib/polyphony/core/sync.rb +57 -12
- data/lib/polyphony/core/thread_pool.rb +42 -5
- data/lib/polyphony/core/throttler.rb +21 -5
- data/lib/polyphony/core/timer.rb +125 -1
- data/lib/polyphony/extensions/exception.rb +36 -6
- data/lib/polyphony/extensions/fiber.rb +238 -57
- data/lib/polyphony/extensions/io.rb +4 -2
- data/lib/polyphony/extensions/kernel.rb +9 -4
- data/lib/polyphony/extensions/object.rb +8 -0
- data/lib/polyphony/extensions/openssl.rb +3 -1
- data/lib/polyphony/extensions/socket.rb +458 -39
- data/lib/polyphony/extensions/thread.rb +108 -43
- data/lib/polyphony/extensions/timeout.rb +12 -1
- data/lib/polyphony/extensions.rb +1 -0
- data/lib/polyphony/net.rb +59 -0
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +0 -2
- data/test/test_backend.rb +6 -2
- data/test/test_global_api.rb +0 -23
- data/test/test_resource_pool.rb +1 -1
- data/test/test_throttler.rb +0 -6
- data/test/test_trace.rb +87 -0
- metadata +9 -8
- data/lib/polyphony/core/channel.rb +0 -15
| @@ -5,30 +5,73 @@ require 'socket' | |
| 5 5 | 
             
            require_relative './io'
         | 
| 6 6 | 
             
            require_relative '../core/thread_pool'
         | 
| 7 7 |  | 
| 8 | 
            +
            # BasicSocket extensions
         | 
| 8 9 | 
             
            class BasicSocket
         | 
| 9 | 
            -
               | 
| 10 | 
            +
              # Returns `:backend_recv`. This method is used to tell parsers which read
         | 
| 11 | 
            +
              # method to use for this object.
         | 
| 12 | 
            +
              #
         | 
| 13 | 
            +
              # @return [:backend_recv] use Polyphony.backend_recv to parse from socket
         | 
| 14 | 
            +
              def __read_method__
         | 
| 10 15 | 
             
                :backend_recv
         | 
| 11 16 | 
             
              end
         | 
| 12 17 | 
             
            end
         | 
| 13 18 |  | 
| 14 | 
            -
            # Socket  | 
| 19 | 
            +
            # Socket extensions # TODO: rewrite in C
         | 
| 15 20 | 
             
            class ::Socket
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              # Accepts an incoming connection.
         | 
| 23 | 
            +
              
         | 
| 24 | 
            +
              # @return [TCPSocket] new connection
         | 
| 16 25 | 
             
              def accept
         | 
| 17 26 | 
             
                Polyphony.backend_accept(self, TCPSocket)
         | 
| 18 27 | 
             
              end
         | 
| 19 28 |  | 
| 29 | 
            +
              # call-seq:
         | 
| 30 | 
            +
              #   socket.accept_loop { |conn| ... }
         | 
| 31 | 
            +
              #
         | 
| 32 | 
            +
              # Accepts incoming connections in an infinite loop.
         | 
| 33 | 
            +
              #
         | 
| 34 | 
            +
              # @param &block [Proc] handler block
         | 
| 35 | 
            +
              # @return [void]
         | 
| 20 36 | 
             
              def accept_loop(&block)
         | 
| 21 37 | 
             
                Polyphony.backend_accept_loop(self, TCPSocket, &block)
         | 
| 22 38 | 
             
              end
         | 
| 23 39 |  | 
| 24 40 | 
             
              NO_EXCEPTION = { exception: false }.freeze
         | 
| 25 41 |  | 
| 42 | 
            +
              # Connects to the given address
         | 
| 43 | 
            +
              #
         | 
| 44 | 
            +
              # @param addr [AddrInfo, String] address to connect to
         | 
| 45 | 
            +
              # @return [::Socket] self
         | 
| 26 46 | 
             
              def connect(addr)
         | 
| 27 47 | 
             
                addr = Addrinfo.new(addr) if addr.is_a?(String)
         | 
| 28 48 | 
             
                Polyphony.backend_connect(self, addr.ip_address, addr.ip_port)
         | 
| 49 | 
            +
                self
         | 
| 29 50 | 
             
              end
         | 
| 30 51 |  | 
| 31 52 | 
             
              alias_method :orig_read, :read
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              # call-seq:
         | 
| 55 | 
            +
              #   socket.read -> string
         | 
| 56 | 
            +
              #   socket.read(maxlen) -> string
         | 
| 57 | 
            +
              #   socket.read(maxlen, buf) -> buf
         | 
| 58 | 
            +
              #   socket.read(maxlen, buf, buf_pos) -> buf
         | 
| 59 | 
            +
              #
         | 
| 60 | 
            +
              # Reads from the socket. If `maxlen` is given, reads up to `maxlen` bytes from
         | 
| 61 | 
            +
              # the socket, otherwise reads to `EOF`. If `buf` is given, it is used as the
         | 
| 62 | 
            +
              # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
         | 
| 63 | 
            +
              # given, reads into the given offset (in bytes) in the given buffer. If the
         | 
| 64 | 
            +
              # given buffer offset is negative, it is calculated from the current end of
         | 
| 65 | 
            +
              # the buffer (`-1` means the read data will be appended to the end of the
         | 
| 66 | 
            +
              # buffer).
         | 
| 67 | 
            +
              #
         | 
| 68 | 
            +
              # If no bytes are available and `EOF` is not hit, this method will block until
         | 
| 69 | 
            +
              # the socket is ready to read from.
         | 
| 70 | 
            +
              #
         | 
| 71 | 
            +
              # @param maxlen [Integer, nil] maximum bytes to read from socket
         | 
| 72 | 
            +
              # @param buf [String, nil] buffer to read into
         | 
| 73 | 
            +
              # @param buf_pos [Number] buffer position to read into
         | 
| 74 | 
            +
              # @return [String] buffer used for reading
         | 
| 32 75 | 
             
              def read(maxlen = nil, buf = nil, buf_pos = 0)
         | 
| 33 76 | 
             
                return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
         | 
| 34 77 | 
             
                return Polyphony.backend_recv(self, +'', maxlen, 0) if maxlen
         | 
| @@ -45,19 +88,70 @@ class ::Socket | |
| 45 88 | 
             
                buf
         | 
| 46 89 | 
             
              end
         | 
| 47 90 |  | 
| 91 | 
            +
              # call-seq:
         | 
| 92 | 
            +
              #   socket.recv(maxlen) -> string
         | 
| 93 | 
            +
              #   socket.recv(maxlen, flags) -> string
         | 
| 94 | 
            +
              #   socket.recv(maxlen, flags, buf) -> buf
         | 
| 95 | 
            +
              #
         | 
| 96 | 
            +
              # Receives up to `maxlen` bytes from the socket. If `outbuf` is given, it is
         | 
| 97 | 
            +
              # used as the buffer to receive into, otherwise a new string is allocated and
         | 
| 98 | 
            +
              # used as buffer.
         | 
| 99 | 
            +
              #
         | 
| 100 | 
            +
              # If no bytes are available, this method will block until the socket is ready
         | 
| 101 | 
            +
              # to receive from.
         | 
| 102 | 
            +
              #
         | 
| 103 | 
            +
              # @param maxlen [Integer] maximum bytes to receive
         | 
| 104 | 
            +
              # @param flags [Integer] receive flags
         | 
| 105 | 
            +
              # @param outbuf [String, nil] buffer for reading or nil to allocate new string
         | 
| 106 | 
            +
              # @return [String] receive buffer
         | 
| 48 107 | 
             
              def recv(maxlen, flags = 0, outbuf = nil)
         | 
| 49 108 | 
             
                Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
         | 
| 50 109 | 
             
              end
         | 
| 51 110 |  | 
| 111 | 
            +
              # call-seq:
         | 
| 112 | 
            +
              #   socket.recv_loop { |data| ... }
         | 
| 113 | 
            +
              #   socket.recv_loop(maxlen) { |data| ... }
         | 
| 114 | 
            +
              #   socket.read_loop { |data| ... }
         | 
| 115 | 
            +
              #   socket.read_loop(maxlen) { |data| ... }
         | 
| 116 | 
            +
              #
         | 
| 117 | 
            +
              # Receives up to `maxlen` bytes at a time in an infinite loop. Read buffers
         | 
| 118 | 
            +
              # will be passed to the given block.
         | 
| 119 | 
            +
              #
         | 
| 120 | 
            +
              # @param maxlen [Integer] maximum bytes to receive
         | 
| 121 | 
            +
              # @param &block [Proc] handler block
         | 
| 122 | 
            +
              # @return [void]
         | 
| 52 123 | 
             
              def recv_loop(maxlen = 8192, &block)
         | 
| 53 124 | 
             
                Polyphony.backend_recv_loop(self, maxlen, &block)
         | 
| 54 125 | 
             
              end
         | 
| 55 126 | 
             
              alias_method :read_loop, :recv_loop
         | 
| 56 127 |  | 
| 128 | 
            +
              # call-seq:
         | 
| 129 | 
            +
              #   socket.feed_loop(receiver, method)
         | 
| 130 | 
            +
              #   socket.feed_loop(receiver, method) { |result| ... }
         | 
| 131 | 
            +
              #
         | 
| 132 | 
            +
              # Receives data from the socket in an infinite loop, passing the data to the
         | 
| 133 | 
            +
              # given receiver using the given method. If a block is given, the result of
         | 
| 134 | 
            +
              # the method call to the receiver is passed to the block.
         | 
| 135 | 
            +
              #
         | 
| 136 | 
            +
              # This method can be used to feed data into parser objects. The following
         | 
| 137 | 
            +
              # example shows how to feed data from a socket directly into a MessagePack
         | 
| 138 | 
            +
              # unpacker:
         | 
| 139 | 
            +
              #
         | 
| 140 | 
            +
              #   unpacker = MessagePack::Unpacker.new
         | 
| 141 | 
            +
              #   buffer = []
         | 
| 142 | 
            +
              #   reader = spin do
         | 
| 143 | 
            +
              #     i.feed_loop(unpacker, :feed_each) { |msg| handle_msg(msg) }
         | 
| 144 | 
            +
              #   end
         | 
| 145 | 
            +
              #
         | 
| 146 | 
            +
              # @param receiver [any] receiver object
         | 
| 147 | 
            +
              # @param method [Symbol] method to call
         | 
| 148 | 
            +
              # @param &block [Proc] block to handle result of method call to receiver
         | 
| 149 | 
            +
              # @return [void]
         | 
| 57 150 | 
             
              def feed_loop(receiver, method = :call, &block)
         | 
| 58 151 | 
             
                Polyphony.backend_recv_feed_loop(self, receiver, method, &block)
         | 
| 59 152 | 
             
              end
         | 
| 60 153 |  | 
| 154 | 
            +
              # :no-doc:
         | 
| 61 155 | 
             
              def recvfrom(maxlen, flags = 0)
         | 
| 62 156 | 
             
                buf = +''
         | 
| 63 157 | 
             
                while true
         | 
| @@ -71,43 +165,74 @@ class ::Socket | |
| 71 165 | 
             
                end
         | 
| 72 166 | 
             
              end
         | 
| 73 167 |  | 
| 74 | 
            -
              #  | 
| 75 | 
            -
              #    | 
| 76 | 
            -
              #  | 
| 77 | 
            -
             | 
| 78 | 
            -
              #  | 
| 79 | 
            -
              # | 
| 80 | 
            -
              #  | 
| 81 | 
            -
             | 
| 82 | 
            -
              #  | 
| 83 | 
            -
              # | 
| 84 | 
            -
              # end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
               | 
| 87 | 
            -
             | 
| 168 | 
            +
              # call-seq:
         | 
| 169 | 
            +
              #   socket.readpartial(maxlen) -> string
         | 
| 170 | 
            +
              #   socket.readpartial(maxlen, buf) -> buf
         | 
| 171 | 
            +
              #   socket.readpartial(maxlen, buf, buf_pos) -> buf
         | 
| 172 | 
            +
              #   socket.readpartial(maxlen, buf, buf_pos, raise_on_eof) -> buf
         | 
| 173 | 
            +
              #
         | 
| 174 | 
            +
              # Reads up to `maxlen` from the socket. If `buf` is given, it is used as the
         | 
| 175 | 
            +
              # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
         | 
| 176 | 
            +
              # given, reads into the given offset (in bytes) in the given buffer. If the
         | 
| 177 | 
            +
              # given buffer offset is negative, it is calculated from the current end of
         | 
| 178 | 
            +
              # the buffer (`-1` means the read data will be appended to the end of the
         | 
| 179 | 
            +
              # buffer). If `raise_on_eof` is `true` (the default,) an `EOFError` will be
         | 
| 180 | 
            +
              # raised on `EOF`, otherwise `nil` will be returned.
         | 
| 181 | 
            +
              #
         | 
| 182 | 
            +
              # If no bytes are available and `EOF` is not hit, this method will block until
         | 
| 183 | 
            +
              # the socket is ready to read from.
         | 
| 184 | 
            +
              #
         | 
| 185 | 
            +
              # @param maxlen [Integer, nil] maximum bytes to read from socket
         | 
| 186 | 
            +
              # @param buf [String, nil] buffer to read into
         | 
| 187 | 
            +
              # @param buf_pos [Number] buffer position to read into
         | 
| 188 | 
            +
              # @param raise_on_eof [bool] whether to raise an exception on `EOF`
         | 
| 189 | 
            +
              # @return [String, nil] buffer used for reading or nil on `EOF`
         | 
| 190 | 
            +
              def readpartial(maxlen, buf = +'', buf_pos = 0, raise_on_eof = true)
         | 
| 191 | 
            +
                result = Polyphony.backend_recv(self, buf, maxlen, buf_pos)
         | 
| 88 192 | 
             
                raise EOFError if !result && raise_on_eof
         | 
| 89 193 | 
             
              end
         | 
| 90 194 |  | 
| 91 195 | 
             
              ZERO_LINGER = [0, 0].pack('ii').freeze
         | 
| 92 196 |  | 
| 197 | 
            +
              # Sets the linger option to 0.
         | 
| 198 | 
            +
              #
         | 
| 199 | 
            +
              # @return [::Socket] self
         | 
| 93 200 | 
             
              def dont_linger
         | 
| 94 201 | 
             
                setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, ZERO_LINGER)
         | 
| 202 | 
            +
                self
         | 
| 95 203 | 
             
              end
         | 
| 96 204 |  | 
| 205 | 
            +
              # Sets the `NODELAY` option.
         | 
| 206 | 
            +
              #
         | 
| 207 | 
            +
              # @return [::Socket] self
         | 
| 97 208 | 
             
              def no_delay
         | 
| 98 209 | 
             
                setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
         | 
| 210 | 
            +
                self
         | 
| 99 211 | 
             
              end
         | 
| 100 212 |  | 
| 213 | 
            +
              # Sets the `REUSEADDR` option.
         | 
| 214 | 
            +
              #
         | 
| 215 | 
            +
              # @return [::Socket] self
         | 
| 101 216 | 
             
              def reuse_addr
         | 
| 102 217 | 
             
                setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
         | 
| 218 | 
            +
                self
         | 
| 103 219 | 
             
              end
         | 
| 104 220 |  | 
| 221 | 
            +
              # Sets the `REUSEPORT` option.
         | 
| 222 | 
            +
              #
         | 
| 223 | 
            +
              # @return [::Socket] self
         | 
| 105 224 | 
             
              def reuse_port
         | 
| 106 225 | 
             
                setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEPORT, 1)
         | 
| 226 | 
            +
                self
         | 
| 107 227 | 
             
              end
         | 
| 108 228 |  | 
| 109 229 | 
             
              class << self
         | 
| 110 230 | 
             
                alias_method :orig_getaddrinfo, :getaddrinfo
         | 
| 231 | 
            +
                
         | 
| 232 | 
            +
                # Resolves the given addr using a worker thread from the default thread
         | 
| 233 | 
            +
                # pool.
         | 
| 234 | 
            +
                #
         | 
| 235 | 
            +
                # @return [AddrInfo]
         | 
| 111 236 | 
             
                def getaddrinfo(*args)
         | 
| 112 237 | 
             
                  Polyphony::ThreadPool.process { orig_getaddrinfo(*args) }
         | 
| 113 238 | 
             
                end
         | 
| @@ -120,10 +245,16 @@ class ::TCPSocket | |
| 120 245 |  | 
| 121 246 | 
             
              attr_reader :io
         | 
| 122 247 |  | 
| 123 | 
            -
               | 
| 124 | 
            -
                new | 
| 248 | 
            +
              class << self
         | 
| 249 | 
            +
                alias_method :open, :new
         | 
| 125 250 | 
             
              end
         | 
| 126 251 |  | 
| 252 | 
            +
              # Initializes the socket.
         | 
| 253 | 
            +
              #
         | 
| 254 | 
            +
              # @param remote_host [String] remote host
         | 
| 255 | 
            +
              # @param remote_port [Integer] remote port
         | 
| 256 | 
            +
              # @param local_host [String] local host
         | 
| 257 | 
            +
              # @param local_port [Integer] local port
         | 
| 127 258 | 
             
              def initialize(remote_host, remote_port, local_host = nil, local_port = nil)
         | 
| 128 259 | 
             
                remote_addr = Addrinfo.tcp(remote_host, remote_port)
         | 
| 129 260 | 
             
                @io = Socket.new remote_addr.afamily, Socket::SOCK_STREAM
         | 
| @@ -139,37 +270,89 @@ class ::TCPSocket | |
| 139 270 | 
             
              end
         | 
| 140 271 |  | 
| 141 272 | 
             
              alias_method :orig_close, :close
         | 
| 273 | 
            +
              
         | 
| 274 | 
            +
              # Closes the socket.
         | 
| 275 | 
            +
              #
         | 
| 276 | 
            +
              # @return [TCPSocket] self
         | 
| 142 277 | 
             
              def close
         | 
| 143 278 | 
             
                @io ? @io.close : orig_close
         | 
| 279 | 
            +
                self
         | 
| 144 280 | 
             
              end
         | 
| 145 281 |  | 
| 146 282 | 
             
              alias_method :orig_setsockopt, :setsockopt
         | 
| 283 | 
            +
              
         | 
| 284 | 
            +
              # Calls `setsockopt` with the given arguments.
         | 
| 285 | 
            +
              #
         | 
| 286 | 
            +
              # @return [TCPSocket] self
         | 
| 147 287 | 
             
              def setsockopt(*args)
         | 
| 148 288 | 
             
                @io ? @io.setsockopt(*args) : orig_setsockopt(*args)
         | 
| 289 | 
            +
                self
         | 
| 149 290 | 
             
              end
         | 
| 150 291 |  | 
| 151 292 | 
             
              alias_method :orig_closed?, :closed?
         | 
| 293 | 
            +
              
         | 
| 294 | 
            +
              # Returns true if the socket is closed.
         | 
| 295 | 
            +
              #
         | 
| 296 | 
            +
              # @return [bool] is socket closed
         | 
| 152 297 | 
             
              def closed?
         | 
| 153 298 | 
             
                @io ? @io.closed? : orig_closed?
         | 
| 154 299 | 
             
              end
         | 
| 155 300 |  | 
| 301 | 
            +
              # Sets the linger option to 0.
         | 
| 302 | 
            +
              #
         | 
| 303 | 
            +
              # @return [::Socket] self
         | 
| 156 304 | 
             
              def dont_linger
         | 
| 157 | 
            -
                setsockopt( | 
| 305 | 
            +
                setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, ZERO_LINGER)
         | 
| 306 | 
            +
                self
         | 
| 158 307 | 
             
              end
         | 
| 159 308 |  | 
| 309 | 
            +
              # Sets the `NODELAY` option.
         | 
| 310 | 
            +
              #
         | 
| 311 | 
            +
              # @return [::Socket] self
         | 
| 160 312 | 
             
              def no_delay
         | 
| 161 | 
            -
                setsockopt( | 
| 313 | 
            +
                setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
         | 
| 314 | 
            +
                self
         | 
| 162 315 | 
             
              end
         | 
| 163 316 |  | 
| 317 | 
            +
              # Sets the `REUSEADDR` option.
         | 
| 318 | 
            +
              #
         | 
| 319 | 
            +
              # @return [::Socket] self
         | 
| 164 320 | 
             
              def reuse_addr
         | 
| 165 | 
            -
                setsockopt( | 
| 321 | 
            +
                setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
         | 
| 322 | 
            +
                self
         | 
| 166 323 | 
             
              end
         | 
| 167 324 |  | 
| 325 | 
            +
              # Sets the `REUSEPORT` option.
         | 
| 326 | 
            +
              #
         | 
| 327 | 
            +
              # @return [::Socket] self
         | 
| 168 328 | 
             
              def reuse_port
         | 
| 169 329 | 
             
                setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEPORT, 1)
         | 
| 330 | 
            +
                self
         | 
| 170 331 | 
             
              end
         | 
| 171 332 |  | 
| 172 333 | 
             
              alias_method :orig_read, :read
         | 
| 334 | 
            +
             | 
| 335 | 
            +
              # call-seq:
         | 
| 336 | 
            +
              #   socket.read -> string
         | 
| 337 | 
            +
              #   socket.read(maxlen) -> string
         | 
| 338 | 
            +
              #   socket.read(maxlen, buf) -> buf
         | 
| 339 | 
            +
              #   socket.read(maxlen, buf, buf_pos) -> buf
         | 
| 340 | 
            +
              #
         | 
| 341 | 
            +
              # Reads from the socket. If `maxlen` is given, reads up to `maxlen` bytes from
         | 
| 342 | 
            +
              # the socket, otherwise reads to `EOF`. If `buf` is given, it is used as the
         | 
| 343 | 
            +
              # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
         | 
| 344 | 
            +
              # given, reads into the given offset (in bytes) in the given buffer. If the
         | 
| 345 | 
            +
              # given buffer offset is negative, it is calculated from the current end of
         | 
| 346 | 
            +
              # the buffer (`-1` means the read data will be appended to the end of the
         | 
| 347 | 
            +
              # buffer).
         | 
| 348 | 
            +
              #
         | 
| 349 | 
            +
              # If no bytes are available and `EOF` is not hit, this method will block until
         | 
| 350 | 
            +
              # the socket is ready to read from.
         | 
| 351 | 
            +
              #
         | 
| 352 | 
            +
              # @param maxlen [Integer, nil] maximum bytes to read from socket
         | 
| 353 | 
            +
              # @param buf [String, nil] buffer to read into
         | 
| 354 | 
            +
              # @param buf_pos [Number] buffer position to read into
         | 
| 355 | 
            +
              # @return [String] buffer used for reading
         | 
| 173 356 | 
             
              def read(maxlen = nil, buf = nil, buf_pos = 0)
         | 
| 174 357 | 
             
                return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
         | 
| 175 358 | 
             
                return Polyphony.backend_recv(self, +'', maxlen, 0) if maxlen
         | 
| @@ -186,48 +369,131 @@ class ::TCPSocket | |
| 186 369 | 
             
                buf
         | 
| 187 370 | 
             
              end
         | 
| 188 371 |  | 
| 372 | 
            +
              # call-seq:
         | 
| 373 | 
            +
              #   socket.recv(maxlen) -> string
         | 
| 374 | 
            +
              #   socket.recv(maxlen, flags) -> string
         | 
| 375 | 
            +
              #   socket.recv(maxlen, flags, buf) -> buf
         | 
| 376 | 
            +
              #
         | 
| 377 | 
            +
              # Receives up to `maxlen` bytes from the socket. If `outbuf` is given, it is
         | 
| 378 | 
            +
              # used as the buffer to receive into, otherwise a new string is allocated and
         | 
| 379 | 
            +
              # used as buffer.
         | 
| 380 | 
            +
              #
         | 
| 381 | 
            +
              # If no bytes are available, this method will block until the socket is ready
         | 
| 382 | 
            +
              # to receive from.
         | 
| 383 | 
            +
              #
         | 
| 384 | 
            +
              # @param maxlen [Integer] maximum bytes to receive
         | 
| 385 | 
            +
              # @param flags [Integer] receive flags
         | 
| 386 | 
            +
              # @param outbuf [String, nil] buffer for reading or nil to allocate new string
         | 
| 387 | 
            +
              # @return [String] receive buffer
         | 
| 189 388 | 
             
              def recv(maxlen, flags = 0, outbuf = nil)
         | 
| 190 389 | 
             
                Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
         | 
| 191 390 | 
             
              end
         | 
| 192 391 |  | 
| 392 | 
            +
              # call-seq:
         | 
| 393 | 
            +
              #   socket.recv_loop { |data| ... }
         | 
| 394 | 
            +
              #   socket.recv_loop(maxlen) { |data| ... }
         | 
| 395 | 
            +
              #   socket.read_loop { |data| ... }
         | 
| 396 | 
            +
              #   socket.read_loop(maxlen) { |data| ... }
         | 
| 397 | 
            +
              #
         | 
| 398 | 
            +
              # Receives up to `maxlen` bytes at a time in an infinite loop. Read buffers
         | 
| 399 | 
            +
              # will be passed to the given block.
         | 
| 400 | 
            +
              #
         | 
| 401 | 
            +
              # @param maxlen [Integer] maximum bytes to receive
         | 
| 402 | 
            +
              # @param &block [Proc] handler block
         | 
| 403 | 
            +
              # @return [void]
         | 
| 193 404 | 
             
              def recv_loop(maxlen = 8192, &block)
         | 
| 194 405 | 
             
                Polyphony.backend_recv_loop(self, maxlen, &block)
         | 
| 195 406 | 
             
              end
         | 
| 196 407 | 
             
              alias_method :read_loop, :recv_loop
         | 
| 197 408 |  | 
| 409 | 
            +
              # call-seq:
         | 
| 410 | 
            +
              #   socket.feed_loop(receiver, method)
         | 
| 411 | 
            +
              #   socket.feed_loop(receiver, method) { |result| ... }
         | 
| 412 | 
            +
              #
         | 
| 413 | 
            +
              # Receives data from the socket in an infinite loop, passing the data to the
         | 
| 414 | 
            +
              # given receiver using the given method. If a block is given, the result of
         | 
| 415 | 
            +
              # the method call to the receiver is passed to the block.
         | 
| 416 | 
            +
              #
         | 
| 417 | 
            +
              # This method can be used to feed data into parser objects. The following
         | 
| 418 | 
            +
              # example shows how to feed data from a socket directly into a MessagePack
         | 
| 419 | 
            +
              # unpacker:
         | 
| 420 | 
            +
              #
         | 
| 421 | 
            +
              #   unpacker = MessagePack::Unpacker.new
         | 
| 422 | 
            +
              #   buffer = []
         | 
| 423 | 
            +
              #   reader = spin do
         | 
| 424 | 
            +
              #     i.feed_loop(unpacker, :feed_each) { |msg| handle_msg(msg) }
         | 
| 425 | 
            +
              #   end
         | 
| 426 | 
            +
              #
         | 
| 427 | 
            +
              # @param receiver [any] receiver object
         | 
| 428 | 
            +
              # @param method [Symbol] method to call
         | 
| 429 | 
            +
              # @param &block [Proc] block to handle result of method call to receiver
         | 
| 430 | 
            +
              # @return [void]
         | 
| 198 431 | 
             
              def feed_loop(receiver, method = :call, &block)
         | 
| 199 432 | 
             
                Polyphony.backend_recv_feed_loop(self, receiver, method, &block)
         | 
| 200 433 | 
             
              end
         | 
| 201 434 |  | 
| 202 | 
            -
              #  | 
| 203 | 
            -
              #    | 
| 204 | 
            -
              #  | 
| 205 | 
            -
             | 
| 206 | 
            -
              #  | 
| 207 | 
            -
              # | 
| 208 | 
            -
              #  | 
| 209 | 
            -
             | 
| 210 | 
            -
              #  | 
| 211 | 
            -
              # | 
| 212 | 
            -
              # end
         | 
| 213 | 
            -
             | 
| 435 | 
            +
              # call-seq:
         | 
| 436 | 
            +
              #   socket.readpartial(maxlen) -> string
         | 
| 437 | 
            +
              #   socket.readpartial(maxlen, buf) -> buf
         | 
| 438 | 
            +
              #   socket.readpartial(maxlen, buf, buf_pos) -> buf
         | 
| 439 | 
            +
              #   socket.readpartial(maxlen, buf, buf_pos, raise_on_eof) -> buf
         | 
| 440 | 
            +
              #
         | 
| 441 | 
            +
              # Reads up to `maxlen` from the socket. If `buf` is given, it is used as the
         | 
| 442 | 
            +
              # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
         | 
| 443 | 
            +
              # given, reads into the given offset (in bytes) in the given buffer. If the
         | 
| 444 | 
            +
              # given buffer offset is negative, it is calculated from the current end of
         | 
| 445 | 
            +
              # the buffer (`-1` means the read data will be appended to the end of the
         | 
| 446 | 
            +
              # buffer). If `raise_on_eof` is `true` (the default,) an `EOFError` will be
         | 
| 447 | 
            +
              # raised on `EOF`, otherwise `nil` will be returned.
         | 
| 448 | 
            +
              #
         | 
| 449 | 
            +
              # If no bytes are available and `EOF` is not hit, this method will block until
         | 
| 450 | 
            +
              # the socket is ready to read from.
         | 
| 451 | 
            +
              #
         | 
| 452 | 
            +
              # @param maxlen [Integer, nil] maximum bytes to read from socket
         | 
| 453 | 
            +
              # @param buf [String, nil] buffer to read into
         | 
| 454 | 
            +
              # @param buf_pos [Number] buffer position to read into
         | 
| 455 | 
            +
              # @param raise_on_eof [bool] whether to raise an exception on `EOF`
         | 
| 456 | 
            +
              # @return [String, nil] buffer used for reading or nil on `EOF`
         | 
| 214 457 | 
             
              def readpartial(maxlen, str = +'', buffer_pos = 0, raise_on_eof = true)
         | 
| 215 458 | 
             
                result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
         | 
| 216 459 | 
             
                raise EOFError if !result && raise_on_eof
         | 
| 217 460 | 
             
                result
         | 
| 218 461 | 
             
              end
         | 
| 219 462 |  | 
| 220 | 
            -
               | 
| 221 | 
            -
             | 
| 222 | 
            -
               | 
| 223 | 
            -
             | 
| 463 | 
            +
              # Performs a non-blocking read from the socket of up to `maxlen` bytes. If
         | 
| 464 | 
            +
              # `buf` is given, it is used as the read buffer, otherwise a new string will
         | 
| 465 | 
            +
              # be allocated. If the socket is not ready for reading and `exception` is
         | 
| 466 | 
            +
              # true, an `IO::WaitReadable` will be raised. If the socket is not ready for
         | 
| 467 | 
            +
              # reading and `exception` is false, `:wait_readable` is returned.
         | 
| 468 | 
            +
              #
         | 
| 469 | 
            +
              # @param maxlen [Integer] maximum bytes to read
         | 
| 470 | 
            +
              # @param buf [String, nil] read buffer
         | 
| 471 | 
            +
              # @param exception [bool] whether to raise an exception if not ready for reading
         | 
| 472 | 
            +
              # @return [String, :wait_readable] read buffer
         | 
| 473 | 
            +
              def read_nonblock(len, buf = nil, exception: true)
         | 
| 474 | 
            +
                @io.read_nonblock(len, buf, exception: exception)
         | 
| 475 | 
            +
              end
         | 
| 476 | 
            +
             | 
| 477 | 
            +
              # Performs a non-blocking to the socket. If the socket is not ready for
         | 
| 478 | 
            +
              # writing and `exception` is true, an `IO::WaitWritable` will be raised. If
         | 
| 479 | 
            +
              # the socket is not ready for writing and `exception` is false,
         | 
| 480 | 
            +
              # `:wait_writable` is returned.
         | 
| 481 | 
            +
              #
         | 
| 482 | 
            +
              # @param buf [String, nil] write buffer
         | 
| 483 | 
            +
              # @param exception [bool] whether to raise an exception if not ready for reading
         | 
| 484 | 
            +
              # @return [Integer, :wait_readable] number of bytes written
         | 
| 224 485 | 
             
              def write_nonblock(buf, exception: true)
         | 
| 225 486 | 
             
                @io.write_nonblock(buf, exception: exception)
         | 
| 226 487 | 
             
              end
         | 
| 227 488 | 
             
            end
         | 
| 228 489 |  | 
| 229 | 
            -
            #  | 
| 490 | 
            +
            # TCPServer extensions
         | 
| 230 491 | 
             
            class ::TCPServer
         | 
| 492 | 
            +
             | 
| 493 | 
            +
              # Initializes the TCP server socket.
         | 
| 494 | 
            +
              #
         | 
| 495 | 
            +
              # @param hostname [String, nil] hostname to connect to
         | 
| 496 | 
            +
              # @param port [Integer] port to connect to
         | 
| 231 497 | 
             
              def initialize(hostname = nil, port = 0)
         | 
| 232 498 | 
             
                addr = Addrinfo.tcp(hostname, port)
         | 
| 233 499 | 
             
                @io = Socket.new addr.afamily, Socket::SOCK_STREAM
         | 
| @@ -236,26 +502,53 @@ class ::TCPServer | |
| 236 502 | 
             
              end
         | 
| 237 503 |  | 
| 238 504 | 
             
              alias_method :orig_accept, :accept
         | 
| 505 | 
            +
             | 
| 506 | 
            +
              # Accepts an incoming connection.
         | 
| 507 | 
            +
              
         | 
| 508 | 
            +
              # @return [TCPSocket] new connection
         | 
| 239 509 | 
             
              def accept
         | 
| 240 510 | 
             
                Polyphony.backend_accept(@io, TCPSocket)
         | 
| 241 511 | 
             
              end
         | 
| 242 512 |  | 
| 513 | 
            +
              # call-seq:
         | 
| 514 | 
            +
              #   socket.accept_loop { |conn| ... }
         | 
| 515 | 
            +
              #
         | 
| 516 | 
            +
              # Accepts incoming connections in an infinite loop.
         | 
| 517 | 
            +
              #
         | 
| 518 | 
            +
              # @param &block [Proc] handler block
         | 
| 519 | 
            +
              # @return [void]
         | 
| 243 520 | 
             
              def accept_loop(&block)
         | 
| 244 521 | 
             
                Polyphony.backend_accept_loop(@io, TCPSocket, &block)
         | 
| 245 522 | 
             
              end
         | 
| 246 523 |  | 
| 247 524 | 
             
              alias_method :orig_close, :close
         | 
| 525 | 
            +
              
         | 
| 526 | 
            +
              # Closes the server socket.
         | 
| 527 | 
            +
              #
         | 
| 528 | 
            +
              # @return [TCPServer] self
         | 
| 248 529 | 
             
              def close
         | 
| 249 530 | 
             
                @io.close
         | 
| 531 | 
            +
                self
         | 
| 250 532 | 
             
              end
         | 
| 251 533 | 
             
            end
         | 
| 252 534 |  | 
| 253 535 | 
             
            class ::UNIXServer
         | 
| 254 536 | 
             
              alias_method :orig_accept, :accept
         | 
| 255 | 
            -
             | 
| 537 | 
            +
             | 
| 538 | 
            +
              # Accepts an incoming connection.
         | 
| 539 | 
            +
              
         | 
| 540 | 
            +
              # @return [UNIXSocket] new connection
         | 
| 541 | 
            +
              def accept
         | 
| 256 542 | 
             
                Polyphony.backend_accept(self, UNIXSocket)
         | 
| 257 543 | 
             
              end
         | 
| 258 544 |  | 
| 545 | 
            +
              # call-seq:
         | 
| 546 | 
            +
              #   socket.accept_loop { |conn| ... }
         | 
| 547 | 
            +
              #
         | 
| 548 | 
            +
              # Accepts incoming connections in an infinite loop.
         | 
| 549 | 
            +
              #
         | 
| 550 | 
            +
              # @param &block [Proc] handler block
         | 
| 551 | 
            +
              # @return [void]
         | 
| 259 552 | 
             
              def accept_loop(&block)
         | 
| 260 553 | 
             
                Polyphony.backend_accept_loop(self, UNIXSocket, &block)
         | 
| 261 554 | 
             
              end
         | 
| @@ -263,6 +556,28 @@ end | |
| 263 556 |  | 
| 264 557 | 
             
            class ::UNIXSocket
         | 
| 265 558 | 
             
              alias_method :orig_read, :read
         | 
| 559 | 
            +
              
         | 
| 560 | 
            +
              # call-seq:
         | 
| 561 | 
            +
              #   socket.read -> string
         | 
| 562 | 
            +
              #   socket.read(maxlen) -> string
         | 
| 563 | 
            +
              #   socket.read(maxlen, buf) -> buf
         | 
| 564 | 
            +
              #   socket.read(maxlen, buf, buf_pos) -> buf
         | 
| 565 | 
            +
              #
         | 
| 566 | 
            +
              # Reads from the socket. If `maxlen` is given, reads up to `maxlen` bytes from
         | 
| 567 | 
            +
              # the socket, otherwise reads to `EOF`. If `buf` is given, it is used as the
         | 
| 568 | 
            +
              # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
         | 
| 569 | 
            +
              # given, reads into the given offset (in bytes) in the given buffer. If the
         | 
| 570 | 
            +
              # given buffer offset is negative, it is calculated from the current end of
         | 
| 571 | 
            +
              # the buffer (`-1` means the read data will be appended to the end of the
         | 
| 572 | 
            +
              # buffer).
         | 
| 573 | 
            +
              #
         | 
| 574 | 
            +
              # If no bytes are available and `EOF` is not hit, this method will block until
         | 
| 575 | 
            +
              # the socket is ready to read from.
         | 
| 576 | 
            +
              #
         | 
| 577 | 
            +
              # @param maxlen [Integer, nil] maximum bytes to read from socket
         | 
| 578 | 
            +
              # @param buf [String, nil] buffer to read into
         | 
| 579 | 
            +
              # @param buf_pos [Number] buffer position to read into
         | 
| 580 | 
            +
              # @return [String] buffer used for reading
         | 
| 266 581 | 
             
              def read(maxlen = nil, buf = nil, buf_pos = 0)
         | 
| 267 582 | 
             
                return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
         | 
| 268 583 | 
             
                return Polyphony.backend_recv(self, +'', maxlen, 0) if maxlen
         | 
| @@ -279,41 +594,145 @@ class ::UNIXSocket | |
| 279 594 | 
             
                buf
         | 
| 280 595 | 
             
              end
         | 
| 281 596 |  | 
| 597 | 
            +
              # call-seq:
         | 
| 598 | 
            +
              #   socket.recv(maxlen) -> string
         | 
| 599 | 
            +
              #   socket.recv(maxlen, flags) -> string
         | 
| 600 | 
            +
              #   socket.recv(maxlen, flags, buf) -> buf
         | 
| 601 | 
            +
              #
         | 
| 602 | 
            +
              # Receives up to `maxlen` bytes from the socket. If `outbuf` is given, it is
         | 
| 603 | 
            +
              # used as the buffer to receive into, otherwise a new string is allocated and
         | 
| 604 | 
            +
              # used as buffer.
         | 
| 605 | 
            +
              #
         | 
| 606 | 
            +
              # If no bytes are available, this method will block until the socket is ready
         | 
| 607 | 
            +
              # to receive from.
         | 
| 608 | 
            +
              #
         | 
| 609 | 
            +
              # @param maxlen [Integer] maximum bytes to receive
         | 
| 610 | 
            +
              # @param flags [Integer] receive flags
         | 
| 611 | 
            +
              # @param outbuf [String, nil] buffer for reading or nil to allocate new string
         | 
| 612 | 
            +
              # @return [String] receive buffer
         | 
| 282 613 | 
             
              def recv(maxlen, flags = 0, outbuf = nil)
         | 
| 283 614 | 
             
                Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
         | 
| 284 615 | 
             
              end
         | 
| 285 616 |  | 
| 617 | 
            +
              # call-seq:
         | 
| 618 | 
            +
              #   socket.recv_loop { |data| ... }
         | 
| 619 | 
            +
              #   socket.recv_loop(maxlen) { |data| ... }
         | 
| 620 | 
            +
              #   socket.read_loop { |data| ... }
         | 
| 621 | 
            +
              #   socket.read_loop(maxlen) { |data| ... }
         | 
| 622 | 
            +
              #
         | 
| 623 | 
            +
              # Receives up to `maxlen` bytes at a time in an infinite loop. Read buffers
         | 
| 624 | 
            +
              # will be passed to the given block.
         | 
| 625 | 
            +
              #
         | 
| 626 | 
            +
              # @param maxlen [Integer] maximum bytes to receive
         | 
| 627 | 
            +
              # @param &block [Proc] handler block
         | 
| 628 | 
            +
              # @return [void]
         | 
| 286 629 | 
             
              def recv_loop(maxlen = 8192, &block)
         | 
| 287 630 | 
             
                Polyphony.backend_recv_loop(self, maxlen, &block)
         | 
| 288 631 | 
             
              end
         | 
| 289 632 | 
             
              alias_method :read_loop, :recv_loop
         | 
| 290 633 |  | 
| 634 | 
            +
              # call-seq:
         | 
| 635 | 
            +
              #   socket.feed_loop(receiver, method)
         | 
| 636 | 
            +
              #   socket.feed_loop(receiver, method) { |result| ... }
         | 
| 637 | 
            +
              #
         | 
| 638 | 
            +
              # Receives data from the socket in an infinite loop, passing the data to the
         | 
| 639 | 
            +
              # given receiver using the given method. If a block is given, the result of
         | 
| 640 | 
            +
              # the method call to the receiver is passed to the block.
         | 
| 641 | 
            +
              #
         | 
| 642 | 
            +
              # This method can be used to feed data into parser objects. The following
         | 
| 643 | 
            +
              # example shows how to feed data from a socket directly into a MessagePack
         | 
| 644 | 
            +
              # unpacker:
         | 
| 645 | 
            +
              #
         | 
| 646 | 
            +
              #   unpacker = MessagePack::Unpacker.new
         | 
| 647 | 
            +
              #   buffer = []
         | 
| 648 | 
            +
              #   reader = spin do
         | 
| 649 | 
            +
              #     i.feed_loop(unpacker, :feed_each) { |msg| handle_msg(msg) }
         | 
| 650 | 
            +
              #   end
         | 
| 651 | 
            +
              #
         | 
| 652 | 
            +
              # @param receiver [any] receiver object
         | 
| 653 | 
            +
              # @param method [Symbol] method to call
         | 
| 654 | 
            +
              # @param &block [Proc] block to handle result of method call to receiver
         | 
| 655 | 
            +
              # @return [void]
         | 
| 291 656 | 
             
              def feed_loop(receiver, method = :call, &block)
         | 
| 292 657 | 
             
                Polyphony.backend_recv_feed_loop(self, receiver, method, &block)
         | 
| 293 658 | 
             
              end
         | 
| 294 659 |  | 
| 660 | 
            +
              # Sends the given message on the socket.
         | 
| 661 | 
            +
              #
         | 
| 662 | 
            +
              # @param mesg [String] data to send
         | 
| 663 | 
            +
              # @param flags [Integer] send flags
         | 
| 664 | 
            +
              # @return [Integer] number of bytes sent
         | 
| 295 665 | 
             
              def send(mesg, flags)
         | 
| 296 666 | 
             
                Polyphony.backend_send(self, mesg, flags)
         | 
| 297 667 | 
             
              end
         | 
| 298 668 |  | 
| 669 | 
            +
              # Sends one or more strings on the socket. The strings are guaranteed to be
         | 
| 670 | 
            +
              # written as a single blocking operation.
         | 
| 671 | 
            +
              #
         | 
| 672 | 
            +
              # @param *args [Array<String>] string buffers to write
         | 
| 673 | 
            +
              # @return [Integer] number of bytes written
         | 
| 299 674 | 
             
              def write(*args)
         | 
| 300 675 | 
             
                Polyphony.backend_sendv(self, args, 0)
         | 
| 301 676 | 
             
              end
         | 
| 302 677 |  | 
| 678 | 
            +
              # Sends the given message on the socket.
         | 
| 679 | 
            +
              #
         | 
| 680 | 
            +
              # @param mesg [String] data to send
         | 
| 681 | 
            +
              # @return [Integer] number of bytes sent
         | 
| 303 682 | 
             
              def <<(mesg)
         | 
| 304 683 | 
             
                Polyphony.backend_send(self, mesg, 0)
         | 
| 305 684 | 
             
              end
         | 
| 306 685 |  | 
| 686 | 
            +
              # call-seq:
         | 
| 687 | 
            +
              #   socket.readpartial(maxlen) -> string
         | 
| 688 | 
            +
              #   socket.readpartial(maxlen, buf) -> buf
         | 
| 689 | 
            +
              #   socket.readpartial(maxlen, buf, buf_pos) -> buf
         | 
| 690 | 
            +
              #   socket.readpartial(maxlen, buf, buf_pos, raise_on_eof) -> buf
         | 
| 691 | 
            +
              #
         | 
| 692 | 
            +
              # Reads up to `maxlen` from the socket. If `buf` is given, it is used as the
         | 
| 693 | 
            +
              # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
         | 
| 694 | 
            +
              # given, reads into the given offset (in bytes) in the given buffer. If the
         | 
| 695 | 
            +
              # given buffer offset is negative, it is calculated from the current end of
         | 
| 696 | 
            +
              # the buffer (`-1` means the read data will be appended to the end of the
         | 
| 697 | 
            +
              # buffer). If `raise_on_eof` is `true` (the default,) an `EOFError` will be
         | 
| 698 | 
            +
              # raised on `EOF`, otherwise `nil` will be returned.
         | 
| 699 | 
            +
              #
         | 
| 700 | 
            +
              # If no bytes are available and `EOF` is not hit, this method will block until
         | 
| 701 | 
            +
              # the socket is ready to read from.
         | 
| 702 | 
            +
              #
         | 
| 703 | 
            +
              # @param maxlen [Integer, nil] maximum bytes to read from socket
         | 
| 704 | 
            +
              # @param buf [String, nil] buffer to read into
         | 
| 705 | 
            +
              # @param buf_pos [Number] buffer position to read into
         | 
| 706 | 
            +
              # @param raise_on_eof [bool] whether to raise an exception on `EOF`
         | 
| 707 | 
            +
              # @return [String, nil] buffer used for reading or nil on `EOF`
         | 
| 307 708 | 
             
              def readpartial(maxlen, str = +'', buffer_pos = 0, raise_on_eof = true)
         | 
| 308 709 | 
             
                result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
         | 
| 309 710 | 
             
                raise EOFError if !result && raise_on_eof
         | 
| 310 711 | 
             
                result
         | 
| 311 712 | 
             
              end
         | 
| 312 713 |  | 
| 714 | 
            +
              # Performs a non-blocking read from the socket of up to `maxlen` bytes. If
         | 
| 715 | 
            +
              # `buf` is given, it is used as the read buffer, otherwise a new string will
         | 
| 716 | 
            +
              # be allocated. If the socket is not ready for reading and `exception` is
         | 
| 717 | 
            +
              # true, an `IO::WaitReadable` will be raised. If the socket is not ready for
         | 
| 718 | 
            +
              # reading and `exception` is false, `:wait_readable` is returned.
         | 
| 719 | 
            +
              #
         | 
| 720 | 
            +
              # @param maxlen [Integer] maximum bytes to read
         | 
| 721 | 
            +
              # @param buf [String, nil] read buffer
         | 
| 722 | 
            +
              # @param exception [bool] whether to raise an exception if not ready for reading
         | 
| 723 | 
            +
              # @return [String, :wait_readable] read buffer
         | 
| 313 724 | 
             
              def read_nonblock(len, str = nil, exception: true)
         | 
| 314 725 | 
             
                @io.read_nonblock(len, str, exception: exception)
         | 
| 315 726 | 
             
              end
         | 
| 316 727 |  | 
| 728 | 
            +
              # Performs a non-blocking to the socket. If the socket is not ready for
         | 
| 729 | 
            +
              # writing and `exception` is true, an `IO::WaitWritable` will be raised. If
         | 
| 730 | 
            +
              # the socket is not ready for writing and `exception` is false,
         | 
| 731 | 
            +
              # `:wait_writable` is returned.
         | 
| 732 | 
            +
              #
         | 
| 733 | 
            +
              # @param buf [String, nil] write buffer
         | 
| 734 | 
            +
              # @param exception [bool] whether to raise an exception if not ready for reading
         | 
| 735 | 
            +
              # @return [Integer, :wait_readable] number of bytes written
         | 
| 317 736 | 
             
              def write_nonblock(buf, exception: true)
         | 
| 318 737 | 
             
                @io.write_nonblock(buf, exception: exception)
         | 
| 319 738 | 
             
              end
         |