Forum: Ruby Thread IO

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
2a1dac2b23b80e53d94d3ebc9122acd9?d=identicon&s=25 Martin Ceronio (mydoghasworms)
on 2009-02-26 11:35
What can I use as a general purpose duplexed IO object to communicate
via data streams between two threads? I would like something similar to
TCPSocket, but without the need to communicate via a network port.
2a1dac2b23b80e53d94d3ebc9122acd9?d=identicon&s=25 Martin Ceronio (mydoghasworms)
on 2009-02-26 11:51
Martin Ceronio wrote:
> What can I use as a general purpose duplexed IO object to communicate
> via data streams between two threads? I would like something similar to
> TCPSocket, but without the need to communicate via a network port.

I've thought of creating two pipes (because I understand by nature that
one end is read-only and the other write-only) and then giving each
thread a read end and a write end, as shown below. The problem is that
this hangs indefinitely, perhaps just highlighting my lack of
understanding of how IO works (if that is the case, please be so kind as
to put me out of my misery and point me to a good primer).

So, here goes:

gui_rd, ctr_wr = IO.pipe
ctr_rd, gui_wr = IO.pipe

gui = Thread.new(gui_rd, gui_wr) {|gui_rd, gui_wr|
  gui_wr << "I've got something for you\n"
  puts gui_rd.gets
}

ctr = Thread.new(ctr_rd, ctr_wr) {|ctr_rd, ctr_wr|
  puts ctr_rd.gets
  ctr_wr << "Right back at you\n"
}

gui.join
ctr.join
42773b24e0c3fb506a8a875c058a9dd7?d=identicon&s=25 Dylan Evans (Guest)
on 2009-02-26 12:49
(Received via mailing list)
That's a pretty standard way to do IPC and is generally a good idea.
Also
your code works for me. What ruby implementation are you using?


On Thu, Feb 26, 2009 at 8:50 PM, Martin Ceronio
2a1dac2b23b80e53d94d3ebc9122acd9?d=identicon&s=25 Martin Ceronio (mydoghasworms)
on 2009-02-26 13:02
I am running on
ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32]
(from the one-click installer)
2a1dac2b23b80e53d94d3ebc9122acd9?d=identicon&s=25 Martin Ceronio (mydoghasworms)
on 2009-02-26 13:14
I have just tried it on

ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]

and there it works!

If this is a Windows issue, is there possibly a workaround?
2a1dac2b23b80e53d94d3ebc9122acd9?d=identicon&s=25 Martin Ceronio (mydoghasworms)
on 2009-02-26 13:19
Martin Ceronio wrote:
> I am running on
> ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32]
> (from the one-click installer)

Oh yes, and I'm running on Windows XP SP2 if that makes a difference.
2a1dac2b23b80e53d94d3ebc9122acd9?d=identicon&s=25 Martin Ceronio (mydoghasworms)
on 2009-02-26 13:48
The other thing to note is that this does not happen with TCPSocket
(again on Windows in my case), because the following works for me:

require 'socket'
require 'gserver'

class MyServer < GServer
  def initialize(port=9876, *args)
    super(port, *args)
  end
  def serve(io)
    puts io.gets
    stop
  end
end

server = MyServer.new.start
TCPSocket.new("localhost", 9876) << "I have found you!\n"
server.join

So other than the pipes and the sockets, is there another IO object I
can use to communicate between two threads?
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-02-26 14:04
(Received via mailing list)
2009/2/26 Martin Ceronio <martin.ceronio@absa.co.za>:
> What can I use as a general purpose duplexed IO object to communicate
> via data streams between two threads? I would like something similar to
> TCPSocket, but without the need to communicate via a network port.

You can use class Queue.

Kind regards

robert
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-02-26 14:14
Martin Ceronio wrote:
> What can I use as a general purpose duplexed IO object to communicate
> via data streams between two threads? I would like something similar to
> TCPSocket, but without the need to communicate via a network port.

Socket.pair is the low-level way of doing this (equivalent to
socketpair())

But if it's just between two Ruby threads, I'd use Queue or SizedQueue.
See thread.rb in the standard library.
2a1dac2b23b80e53d94d3ebc9122acd9?d=identicon&s=25 Martin Ceronio (mydoghasworms)
on 2009-02-26 14:23
Thanks very much Robert and Brian.

This might be what I am looking for. I will do some investigation to see
if I can use this instead.

Now, it would still be interesting to know why the pipes worked on Linux
but not on Windows.
42773b24e0c3fb506a8a875c058a9dd7?d=identicon&s=25 Dylan Evans (Guest)
on 2009-02-27 04:28
(Received via mailing list)
On Thu, Feb 26, 2009 at 11:22 PM, Martin Ceronio
<martin.ceronio@absa.co.za>wrote:

> Thanks very much Robert and Brian.
>
> This might be what I am looking for. I will do some investigation to see
> if I can use this instead.
>
> Now, it would still be interesting to know why the pipes worked on Linux
> but not on Windows.

Good question. Might be a bug. Not sure how pipes are implemented in
windows
but in linux they're native. Maybe it would work in jruby.
2a1dac2b23b80e53d94d3ebc9122acd9?d=identicon&s=25 Martin Ceronio (mydoghasworms)
on 2009-02-27 06:48
Thanks Dylan.

It turns out that what I needed after all was the Queue solution, so
fortunately I won't have to rely on pipes at this point in time.
This topic is locked and can not be replied to.