a __real__ drb question

A

Ara.T.Howard

now that i've already stuck my foot in my mouth, i'd like to ask a real drb
question.

say you've got a thread accessing an obj which is being served by drb:

require 'drb/drb'

mode = ARGV.shift || 'server'

class Q
def initialize; @q=[]; end
def push obj; @q << obj; end
def pop; @q.shift; end
end

case mode
when 'server'
q = Q.new
#
# is this safe?
#
Thread.new{loop{ sleep 2; q.push Time.now }}

DRb.start_service nil, q
uri = DRb.uri
puts "ruby #{ $0 } client #{ DRb.uri }"
DRb.thread.join

when 'client'
uri = ARGV.shift
DRb.start_service nil, nil
q = DRbObject.new nil, uri
loop do
obj = q.pop
p obj
q.push 42
sleep 0.5
end
end


my understanding is that access to the object via DRb is provided by multiple
synchronized threads. eg. only one DRb thread would be accessing your object
at once so you generally don't need to consider thread coordination. in this
case, however, i have a thread outside of DRb accessing the object - what sort
of coordination would this require? perhaps it would be better to have the
thread obtain a DRbObject itself and allow the DRb library to handle all the
coordination?

eg.

....
when 'server'
q = Q.new
DRb.start_service nil, q
uri = DRb.uri
#
# safe?
#
q = DRbObject.new nil, uri
Thread.new{loop{ sleep 2; q.push Time.now }}

puts "ruby #{ $0 } client #{ DRb.uri }"
DRb.thread.join
....

comments?

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it; and a weed grows, even though we do
| not love it. --Dogen
===============================================================================
 
R

Robert Klemme

Ara.T.Howard said:
now that i've already stuck my foot in my mouth, i'd like to ask a real drb
question.

say you've got a thread accessing an obj which is being served by drb:

require 'drb/drb'

mode = ARGV.shift || 'server'

class Q
def initialize; @q=[]; end
def push obj; @q << obj; end
def pop; @q.shift; end
end

case mode
when 'server'
q = Q.new
#
# is this safe?
#
Thread.new{loop{ sleep 2; q.push Time.now }}

DRb.start_service nil, q
uri = DRb.uri
puts "ruby #{ $0 } client #{ DRb.uri }"
DRb.thread.join

when 'client'
uri = ARGV.shift
DRb.start_service nil, nil
q = DRbObject.new nil, uri
loop do
obj = q.pop
p obj
q.push 42
sleep 0.5
end
end


my understanding is that access to the object via DRb is provided by multiple
synchronized threads. eg. only one DRb thread would be accessing your object
at once so you generally don't need to consider thread coordination.

That was not my understanding and tests seem to back this:

in this
case, however, i have a thread outside of DRb accessing the object - what sort
of coordination would this require? perhaps it would be better to have the
thread obtain a DRbObject itself and allow the DRb library to handle all the
coordination?

A general note about concurrency that applies here as well: Typically
"automated" synchronization is not done because no automated mechanism can
know the granularity of concurrency needed. You might even access an
instance concurrently in a proper way without synchronization (e.g. if the
instance does not contain any state itself). Another example is a set of
operations that has to be done exclusively; a typical example is check for
presence and then


eg.

...
when 'server'
q = Q.new
DRb.start_service nil, q
uri = DRb.uri
#
# safe?
#
q = DRbObject.new nil, uri
Thread.new{loop{ sleep 2; q.push Time.now }}

puts "ruby #{ $0 } client #{ DRb.uri }"
DRb.thread.join
...

comments?

-a
--
============================================================================
===
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it; and a weed grows, even though we do
| not love it. --Dogen
============================================================================
===
 
R

Robert Klemme

*** forget the other posting, I accidentally hit 'send' ***


Ara.T.Howard said:
now that i've already stuck my foot in my mouth, i'd like to ask a real drb
question.

say you've got a thread accessing an obj which is being served by drb:

require 'drb/drb'

mode = ARGV.shift || 'server'

class Q
def initialize; @q=[]; end
def push obj; @q << obj; end
def pop; @q.shift; end
end

case mode
when 'server'
q = Q.new
#
# is this safe?
#
No.

Thread.new{loop{ sleep 2; q.push Time.now }}

DRb.start_service nil, q
uri = DRb.uri
puts "ruby #{ $0 } client #{ DRb.uri }"
DRb.thread.join

when 'client'
uri = ARGV.shift
DRb.start_service nil, nil
q = DRbObject.new nil, uri
loop do
obj = q.pop
p obj
q.push 42
sleep 0.5
end
end


my understanding is that access to the object via DRb is provided by multiple
synchronized threads. eg. only one DRb thread would be accessing your object
at once so you generally don't need to consider thread coordination.

That was not my understanding and tests back this notion:

DRB started at druby://localhost:8787
#<Thread:0x101d6d88 run>: #<Foo:0x101d7058>: ++++ [0]
#<Thread:0x101d6ae8 run>: #<Foo:0x101d7058>: ++++ [0]
#<Thread:0x101d6848 run>: #<Foo:0x101d7058>: ++++ [0]
#<Thread:0x101d65a8 run>: #<Foo:0x101d7058>: ++++ [0]
#<Thread:0x101d5888 run>: #<Foo:0x101d7058>: ++++ [0]
#<Thread:0x101d6d88 run>: #<Foo:0x101d7058>: ---- [0]
#<Thread:0x101d6d88 run>: #<Foo:0x101d7058>: ++++ [1]
#<Thread:0x101d6848 run>: #<Foo:0x101d7058>: ---- [0]
#<Thread:0x101d65a8 run>: #<Foo:0x101d7058>: ---- [0]
#<Thread:0x101d6848 run>: #<Foo:0x101d7058>: ++++ [1]
#<Thread:0x101d65a8 run>: #<Foo:0x101d7058>: ++++ [1]
#<Thread:0x101d6ae8 run>: #<Foo:0x101d7058>: ---- [0]
#<Thread:0x101d6ae8 run>: #<Foo:0x101d7058>: ++++ [1]
#<Thread:0x101d6d88 run>: #<Foo:0x101d7058>: ---- [1]
#<Thread:0x101d6d88 run>: #<Foo:0x101d7058>: ++++ [2]
#<Thread:0x101d65a8 run>: #<Foo:0x101d7058>: ---- [1]
....

(server output, see code attached)
in this
case, however, i have a thread outside of DRb accessing the object - what sort
of coordination would this require? perhaps it would be better to have the
thread obtain a DRbObject itself and allow the DRb library to handle all the
coordination?

A general note about concurrency that applies here as well: Typically
"automated" synchronization is not done because no automated mechanism can
know the granularity of concurrency needed. You might even access an
instance concurrently in a proper way without synchronization (e.g. if the
instance does not contain any state itself). Another case is a set of
operations that has to be done exclusively; a typical example is check for
presence of something and then act depending on the presence like in:

mutex.synchronize do
if foo.has_data?
puts foo.get_data
else
foo.set_data "something"
end
end

That's why typically no synchronization is done automatically.

Kind regards

robert
 
R

Robert Klemme

Did I say I included the source code? Darn...

robert


#!/usr/bin/ruby

require 'drb/drb'

URI="druby://localhost:8787"


module Kernel
private

def tputs(*a)
th = Thread.current.inspect

a.each do |arg|
puts "#{th}: #{a}"
end
end
end

class Foo
def test(*a)
tputs "#{self.inspect}: ++++ #{a.inspect}"
sleep( 1 + rand( 3 ) )
Thread.pass
tputs "#{self.inspect}: ---- #{a.inspect}"
end
end


mode = ARGV.shift || 'server'
time = ARGV.shift || 60

case mode
when 'server'
obj = Foo.new

drb = DRb.start_service URI, obj
puts "DRB started at #{URI}"
sleep time
puts "Stopping DRB..."
drb.stop_service
DRb.thread.join
puts "DRB terminated"

when 'client'
# a single client
DRb.start_service
obj = DRbObject.new_with_uri(URI)

10.times do |i|
puts i
obj.test i
end

when 'multi'
# multiple clients
DRb.start_service
threads = []

5.times do |th|
threads << Thread.new(th) do |id|
o = DRbObject.new_with_uri(URI)

5.times do |i|
puts "client #{id}: #{i}"
o.test i
end
end
end

threads.each {|t| t.join}
end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

drb question 1
drb load limit 3
drb application in bots 0
DRB class in array 7
aboout DRb... 5
question DRb class definition share or not share 2
DRB Program Error 2
Drb and mystery ports (and Queue question) 3

Members online

Forum statistics

Threads
474,262
Messages
2,571,048
Members
48,769
Latest member
Clifft

Latest Threads

Top