Robert Klemme wrote:
> On 10/19/2009 02:51 PM, Daniel Bush wrote:
>> 
>>       puts "#{Thread.current} received #{data}... "
>>     end
>>     client.close
>> 
>> on @socket which was set up like this:
>> 
>>     @socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
>>     @sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost')
>>     @socket.bind( @sockaddr )
>>     @socket.listen( 100 )
> 
> This won't work.  You can have only 1 acceptor thread per server socket.
>   Typically you dispatch processing *after* the accept to a thread
> (either newly created or taken from a pool).
> 
> I have no idea what the interpreter is going to do if you have multiple
> threads trying to accept from the same socket.  In the best case #accept
> is synchronized and only one thread gets to enter it.  In worse
> scenarios anything bad may happen.

Ok, I wasn't sure if it was appropriate having >1 thread per socket 
instance.  It *appears* to work ok on ruby 1.9 up to about 100 socket 
connections - not that that means anything when it comes to testing 
stuff with threads.  Maybe if I do 100,000+ I might elicit some type of 
error.

I was intending to process the result of accept in another pool but I 
was toying with the idea of having 2-3 threads waiting on #accept 
assuming no synchronisation issues.  I didn't know if it really mattered 
or not.  It might make a difference if you have a large number of 
connections coming in depending on what the acceptor is doing in 
addition; I wasn't sure.

I guess I'll have to scupper that idea or exhaustively test it to prove 
it works and has benefit - both of which are questionable at this point.

> 
>> I wanted to create a barrage of requests so next I
>> create a pool of requester threads which each run
>> something like this:
>> 
>>   socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
>>   sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
>>   socket.connect( sockaddr )
>>   socket.puts "request #{i}"
>>   socket.close
> 
> Btw, why don't you use TCPServer and TCPSocket?

yeah I was going to, I was just going off some examples in the 
documentation and trying to cut my teeth on them and writing some tests. 
But I was heading that way.

> 
>> queue.
> See above.
> 
>> I haven't submitted the full code because it uses
>> a threadpool library I'm still building/reviewing.
> 
> I would rather do something like this (sketeched):
> 
> require 'thread'
> queue = Queue.new
> workers = (1..10).map do
>    Thread.new queue do |q|
>      until (cl = q.deq).equal? q
>        # process data from / for client cl
>        begin
>          data = cl.gets.chomp
>          @mutex.synchronize do
>            puts "#{Thread.current} received #{data}..."
>          end
>        ensure
>          cl.close
>        end
>      end
>    end
> end
> 
> server = TCPServer.new ...
> 
> while client = server.accept
>    queue.enq client
> end
>
> # elsewhere
> 
> 
> TCPSocket.open do |sock|
>     sock.puts "request"
> end

Thanks for the example.
I am scratching my head a little with this line:
  until (cl = q.deq).equal? q

I'm familiar with Queue and its behaviour.

Cheers,
Daniel Bush
-- 
Posted via http://www.ruby-forum.com/.