Class: Yahns::Queue
- Inherits:
-
SleepyPenguin::Epoll::IO
- Object
- SleepyPenguin::Epoll::IO
- Yahns::Queue
- Includes:
- SleepyPenguin
- Defined in:
- lib/yahns/queue_epoll.rb
Overview
Copyright © 2013, Eric Wong <[email protected]> and all contributors License: GPLv3 or later (www.gnu.org/licenses/gpl-3.0.txt)
This is the dangerous, low-level epoll interface for sleepy_penguin It is safe as long as you’re aware of all potential concurrency issues given multithreading, GC, and epoll itself.
Constant Summary collapse
- QEV_QUIT =
public
Epoll::OUT
- QEV_RD =
Level Trigger for QueueQuitter
Epoll::IN | Epoll::ONESHOT
- QEV_WR =
Epoll::OUT | Epoll::ONESHOT
Instance Attribute Summary collapse
-
#fdmap ⇒ Object
Yahns::Fdmap.
Class Method Summary collapse
Instance Method Summary collapse
-
#queue_add(io, flags) ⇒ Object
for HTTP and HTTPS servers, we rely on the io writing to us, first flags: QEV_RD/QEV_WR (usually QEV_RD).
-
#queue_del(io) ⇒ Object
use only before hijacking, once hijacked, io may be unusable to us It is not safe to call this unless it is an unarmed EPOLLONESHOT object.
- #thr_init ⇒ Object
-
#worker_thread(logger, max_events) ⇒ Object
returns an array of infinitely running threads.
Instance Attribute Details
#fdmap ⇒ Object
Yahns::Fdmap
10 11 12 |
# File 'lib/yahns/queue_epoll.rb', line 10 def fdmap @fdmap end |
Class Method Details
.new ⇒ Object
17 18 19 |
# File 'lib/yahns/queue_epoll.rb', line 17 def self.new super(SleepyPenguin::Epoll::CLOEXEC) end |
Instance Method Details
#queue_add(io, flags) ⇒ Object
for HTTP and HTTPS servers, we rely on the io writing to us, first flags: QEV_RD/QEV_WR (usually QEV_RD)
23 24 25 26 27 28 |
# File 'lib/yahns/queue_epoll.rb', line 23 def queue_add(io, flags) # order is very important here, this thread cannot do anything with # io once we've issued epoll_ctl() because another thread may use it @fdmap.add(io) epoll_ctl(Epoll::CTL_ADD, io, flags) end |
#queue_del(io) ⇒ Object
use only before hijacking, once hijacked, io may be unusable to us It is not safe to call this unless it is an unarmed EPOLLONESHOT object.
38 39 40 41 42 43 44 |
# File 'lib/yahns/queue_epoll.rb', line 38 def queue_del(io) # order does not really matter here, however Epoll::CTL_DEL # will free up ~200 bytes of unswappable kernel memory, # so we call it first epoll_ctl(Epoll::CTL_DEL, io, 0) @fdmap.forget(io) end |
#thr_init ⇒ Object
30 31 32 33 |
# File 'lib/yahns/queue_epoll.rb', line 30 def thr_init Thread.current[:yahns_rbuf] = "" Thread.current[:yahns_fdmap] = @fdmap end |
#worker_thread(logger, max_events) ⇒ Object
returns an array of infinitely running threads
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/yahns/queue_epoll.rb', line 47 def worker_thread(logger, max_events) Thread.new do thr_init begin epoll_wait(max_events) do |_, io| # don't care for flags for now # Note: we absolutely must not do anything with io after # we've called epoll_ctl on it, io is exclusive to this # thread only until epoll_ctl is called on it. case rv = io.yahns_step when :wait_readable epoll_ctl(Epoll::CTL_MOD, io, QEV_RD) when :wait_writable epoll_ctl(Epoll::CTL_MOD, io, QEV_WR) when :ignore # only used by rack.hijack # we cannot call Epoll::CTL_DEL after hijacking, the hijacker # may have already closed it Likewise, io.fileno is not # expected to work, so we had to erase it from fdmap before hijack when nil, :close # this must be the ONLY place where we call IO#close on # things that got inside the queue @fdmap.sync_close(io) else raise "BUG: #{io.inspect}#yahns_step returned: #{rv.inspect}" end end rescue => e break if closed? # can still happen due to shutdown_timeout Yahns::Log.exception(logger, 'queue loop', e) end while true end end |