about summary refs log tree commit homepage
path: root/lib/dtas/server_loop.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dtas/server_loop.rb')
-rw-r--r--lib/dtas/server_loop.rb55
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/dtas/server_loop.rb b/lib/dtas/server_loop.rb
new file mode 100644
index 0000000..f0936aa
--- /dev/null
+++ b/lib/dtas/server_loop.rb
@@ -0,0 +1,55 @@
+# Copyright (C) 2015 all contributors <dtas-all@nongnu.org>
+# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+
+require_relative '../dtas'
+
+# Used for mpd emulation currently, but dtas-player might use this eventually
+class DTAS::ServerLoop
+  def initialize(listeners, client_class)
+    @rd = {}
+    @wr = {}
+    @rbuf = ''
+    @client_class = client_class
+    listeners.each { |l| @rd[l] = true }
+  end
+
+  def run_forever
+    begin
+      r = IO.select(@rd.keys, @wr.keys) or next
+      r[0].each { |rd| do_read(rd) }
+      r[1].each { |wr| do_write(wr) }
+    end while true
+  end
+
+  def do_write(wr)
+    case wr.dispatch_wr
+    when :wait_readable
+      @wr.delete(wr)
+      @rd[wr] = true
+    when nil
+      @wr.delete(wr)
+      wr.to_io.close
+    # when :wait_writable # do nothing
+    end
+  end
+
+  def do_read(rd)
+    case rd
+    when @client_class
+      case rd.dispatch_rd(@rbuf)
+      when :wait_writable
+        @rd.delete(rd)
+        @wr[rd] = true
+      when nil
+        @rd.delete(rd)
+        rd.to_io.close
+      # when :wait_readable : do nothing
+      end
+    else
+      case io = rd.accept_nonblock(exception: false)
+      when :wait_readable then break
+      when IO then @rd[@client_class.new(io)] = true
+      end while true
+    end
+  end
+end