Class: EventMachine::StreamObject

### Home Classes Methods

### In Files

- lib/em/pure_ruby.rb

### Parent

EventMachine::Selectable

### Methods

- ::new
- #eventable_read
- #eventable_write
- #get_outbound_data_size
- #get_peername
- #heartbeat
- #schedule_close
- #select_for_reading?
- #select_for_writing?
- #send_data

### Files

- ChangeLog
- DEFERRABLES
- EPOLL
- INSTALL
- KEYBOARD
- LEGAL
- LIGHTWEIGHT_CONCURRENCY
- PURE_RUBY
- RELEASE_NOTES
- SMTP
- SPAWNED_PROCESSES
- TODO

### Class/Module Index

Quicksearch

- EventMachine
- EventMachine
- EventMachine::Channel
- EventMachine::Completion
- EventMachine::Connection
- EventMachine::DNS
- EventMachine::DNS::Request
- EventMachine::DNS::RequestIdAlreadyUsed
- EventMachine::DNS::Resolver
- EventMachine::DNS::Socket
- EventMachine::DatagramObject
- EventMachine::DefaultDeferrable
- EventMachine::Deferrable
- EventMachine::DeferrableChildProcess
- EventMachine::Error
- EventMachine::EvmaKeyboard
- EventMachine::EvmaTCPClient
- EventMachine::EvmaTCPServer
- EventMachine::EvmaUDPSocket
- EventMachine::EvmaUNIXClient
- EventMachine::EvmaUNIXServer
- EventMachine::FileNotFoundException
- EventMachine::FileStreamer
- EventMachine::FileWatch
- EventMachine::Iterator
- EventMachine::LoopbreakReader
- EventMachine::PeriodicTimer
- EventMachine::Pool
- EventMachine::ProcessWatch
- EventMachine::Protocols
- EventMachine::Protocols
- EventMachine::Protocols::HeaderAndContentProtocol
- EventMachine::Protocols::HttpClient
- EventMachine::Protocols::HttpClient2
- EventMachine::Protocols::HttpClient2::Request
- EventMachine::Protocols::LineAndTextProtocol
- EventMachine::Protocols::LineProtocol
- EventMachine::Protocols::LineText2
- EventMachine::Protocols::Memcache
- EventMachine::Protocols::Memcache::ParserError
- EventMachine::Protocols::ObjectProtocol
- EventMachine::Protocols::Postgres3
- EventMachine::Protocols::SASLauth
- EventMachine::Protocols::SASLauthclient
- EventMachine::Protocols::SmtpClient
- EventMachine::Protocols::SmtpServer
- EventMachine::Protocols::Socks4
- EventMachine::Protocols::Stomp
- EventMachine::Protocols::Stomp::Message
- EventMachine::Protocols::TcpConnectTester
- EventMachine::Queue
- EventMachine::Reactor
- EventMachine::Selectable
- EventMachine::SpawnedProcess
- EventMachine::StreamObject
- EventMachine::SystemCmd
- EventMachine::ThreadedResource
- EventMachine::TickLoop
- EventMachine::Timer
- EventMachine::UuidGenerator
- EventMachine::YieldBlockFromSpawnedProcess
- Object
- Object::EM
- Object::P
- BufferedTokenizer
- IO
- StringIO
- TestConnection

No matching classes.

# EventMachine::StreamObject

@private

### Public Class Methods

new(io) click to toggle source

    # File lib/em/pure_ruby.rb, line 504
    def initialize io
      super io
      @outbound_q = []
    end

### Public Instance Methods

eventable_read() click to toggle source

Proper nonblocking I/O was added to Ruby 1.8.4 in May 2006. If we have it, then we can read multiple times safely to improve performance. The last-activity clock ASSUMES that we only come here when we have selected readable. TODO, coalesce multiple reads into a single event. TODO, do the function check somewhere else and cache it.

    # File lib/em/pure_ruby.rb, line 538
    def eventable_read
      @last_activity = Reactor.instance.current_loop_time
      begin
        if io.respond_to?(:read_nonblock)
          10.times {
            data = io.read_nonblock(4096)
            EventMachine::event_callback uuid, ConnectionData, data
          }
        else
          data = io.sysread(4096)
          EventMachine::event_callback uuid, ConnectionData, data
        end
      rescue Errno::EAGAIN, Errno::EWOULDBLOCK
        # no-op
      rescue Errno::ECONNRESET, Errno::ECONNREFUSED, EOFError
        @close_scheduled = true
        EventMachine::event_callback uuid, ConnectionUnbound, nil
      end

    end

eventable_write() click to toggle source

Provisional implementation. Will be re-implemented in subclasses. TODO: Complete this implementation. As it stands, this only writes a single packet per cycle. Highly inefficient, but required unless we're running on a Ruby with proper nonblocking I/O (Ruby 1.8.4 built from sources from May 25, 2006 or newer). We need to improve the loop so it writes multiple times, however not more than a certain number of bytes per cycle, otherwise one busy connection could hog output buffers and slow down other connections. Also we should coalesce small writes. URGENT TODO: Coalesce small writes. They are a performance killer. The last-activity recorder ASSUMES we'll only come here if we've selected writable.

    # File lib/em/pure_ruby.rb, line 571
    def eventable_write
      # coalesce the outbound array here, perhaps
      @last_activity = Reactor.instance.current_loop_time
      while data = @outbound_q.shift do
        begin
          data = data.to_s
          w = if io.respond_to?(:write_nonblock)
                io.write_nonblock data
              else
                io.syswrite data
              end

          if w < data.length
            @outbound_q.unshift data[w..-1]
            break
          end
        rescue Errno::EAGAIN
          @outbound_q.unshift data
        rescue EOFError, Errno::ECONNRESET, Errno::ECONNREFUSED
          @close_scheduled = true
          @outbound_q.clear
        end
      end

    end

get_outbound_data_size() click to toggle source

get_outbound_data_size

    # File lib/em/pure_ruby.rb, line 624
    def get_outbound_data_size
      @outbound_q.inject(0) {|memo,obj| memo += (obj || "").length}
    end

get_peername() click to toggle source

get_peername This is defined in the normal way on connected stream objects. Return an object that is suitable for passing to Socket#unpack_sockaddr_in or variants. We could also use a convenience method that did the unpacking automatically.

    # File lib/em/pure_ruby.rb, line 619
    def get_peername
      io.getpeername
    end

heartbeat() click to toggle source

    # File lib/em/pure_ruby.rb, line 628
    def heartbeat
      if @inactivity_timeout and @inactivity_timeout > 0 and (@last_activity + @inactivity_timeout) < Reactor.instance.current_loop_time
        schedule_close true
      end
    end

schedule_close(after_writing) click to toggle source

schedule_close The application wants to close the connection.

    # File lib/em/pure_ruby.rb, line 607
    def schedule_close after_writing
      if after_writing
        @close_requested = true
      else
        @close_scheduled = true
      end
    end

select_for_reading?() click to toggle source

If we have to close, or a close-after-writing has been requested, then don't read any more data.

    # File lib/em/pure_ruby.rb, line 511
    def select_for_reading?
      true unless (@close_scheduled || @close_requested)
    end

select_for_writing?() click to toggle source

If we have to close, don't select for writing. Otherwise, see if the protocol is ready to close. If not, see if he has data to send. If a close-after-writing has been requested and the outbound queue is empty, convert the status to close_scheduled.

    # File lib/em/pure_ruby.rb, line 520
    def select_for_writing?
      unless @close_scheduled
        if @outbound_q.empty?
          @close_scheduled = true if @close_requested
          false
        else
          true
        end
      end
    end

send_data(data) click to toggle source

send_data

    # File lib/em/pure_ruby.rb, line 598
    def send_data data
      # TODO, coalesce here perhaps by being smarter about appending to @outbound_q.last?
      unless @close_scheduled or @close_requested or !data or data.length <= 0
        @outbound_q << data.to_s
      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.