# A flaw in tuplespace implementation?

**URL:** <https://www.ruby-forum.com/t/a-flaw-in-tuplespace-implementation/58081>\
**Category:** Ruby\
**Created:** [April 18, 2006, 9:31am UTC](https://www.ruby-forum.com/t/a-flaw-in-tuplespace-implementation/58081 "2006-04-18T09:31:46Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![guest](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/8dc957/32.png) [@guest](https://www.ruby-forum.com/u/guest)\
**Post date:** [April 18, 2006, 9:31am UTC](https://www.ruby-forum.com/t/a-flaw-in-tuplespace-implementation/58081/1 "2006-04-18T09:31:46Z")

</div>

it seems tuplespace’s read operation is not considered important  
somehow. consider this:

class HelloWorld

# include DRbUndumped

```
attr_writer :str
def initialize(str)
	@str = str
end
def _dump#(*args, &block)

```

# Marshal.dump(@str, \*args, &block)

```
end
def HelloWorld._load#(*args, &block)

```

# HelloWorld.new(Marshal.load(\*args, &block))

```
end
def to_s
	@str
end

```

end

i created a simple hello world class, and released its object into the  
tuplespace. i then created a simple process doing indefinite loop of  
reading the object, and another one reading _and_ modifying the object.

so what is the problem you say? i don’t want to use pass-by-reference  
and DRbUndumped, so that each reader process actually gets a copy of the  
object instead of a reference to it. to do that, i have to define my own  
marshalling method. after a few run, i realized that the tuplespace  
seems only need to see a \_dump and a \_load, instead of marshal\_dump and  
marshal\_load, and that the tuplespace doesn’t even bother if there is no  
parameter given in the \_dump and \_load or if there is no operation  
within (returning nil). but the result is still a pass-by-reference. try  
uncommenting the above class code, and something similar to this will  
occur:

in `init_with_ary': undefined method`size’ for  
#DRb::DRbUnknown:0x28d21d0 (NoMethodError)

any suggestion, or is tuplespace’s read operation isn’t as important as  
take operation? is this a flaw?

---

<div class="post-metadata">

**Author:** ![guest](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/8dc957/32.png) [@guest](https://www.ruby-forum.com/u/guest)\
**Post date:** [April 19, 2006, 9:24pm UTC](https://www.ruby-forum.com/t/a-flaw-in-tuplespace-implementation/58081/2 "2006-04-19T21:24:28Z")

</div>

On Apr 18, 2006, at 12:31 AM, Guest wrote:

> so what is the problem you say? i don’t want to use pass-by-reference  
> and DRbUndumped, so that each reader process actually gets a copy  
> of the  
> object instead of a reference to it.

This is exactly how DRb works by default.

> to do that, i have to define my own marshalling method.

No you don’t.

DRb takes care of this for you.

You don’t need to do anything other that make sure the class exists  
on all processes that will hold it.

> try uncommenting the above class code, and something similar to  
> this will  
> occur:
> 
> in `init_with_ary': undefined method `size’ for  
> #DRb::DRbUnknown:0x28d21d0 (NoMethodError)

If you ever get a DRb::DRbUnknown object you don’t have the class  
available on one of your remote processes. Fix that problem first.

The second problem is that you seem to be passing an object that is  
neither an Array nor a Hash into the Tuplespace. The code you gave  
didn’t specify how you were adding the object to the Tuplespace, so a  
full example is necessary to figure out what’s gone wrong.

> any suggestion, or is tuplespace’s read operation isn’t as  
> important as  
> take operation? is this a flaw?

There is no flaw in Tuplespace. What you want to do works out of the  
box. Adding extra marshalling doesn’t do anything since ruby’s built-  
in Marshal does that work for you.

Here’s an example that illustrates what you want. Each slave process  
gets a copy of the object, not a reference to it. You only need to  
have the class exist in every process that will hold the object:

$ cat ts.rb  
require ‘drb’  
require ‘rinda/tuplespace’  
require ‘x’

ts = Rinda::TupleSpace.new  
DRb.start\_service nil, ts  
puts DRb.uri  
DRb.thread.join

$ cat master.rb  
require ‘drb’  
require ‘x’

DRb.start\_service

ts = DRbObject.new nil, ARGV.shift

x = X.new  
x.value = 0

ts.write [:x, x]

$ cat slave.rb  
require ‘drb’  
require ‘x’

DRb.start\_service

ts = DRbObject.new nil, ARGV.shift

obj = ts.read [:x, nil]

p obj.last  
p obj.last.value  
obj.last.value = 100  
p obj.last.value

$ cat x.rb  
class X  
attr\_accessor :value  
end

$ ruby ts.rb &  
druby://kaa.coop.robotcoop.com:52189  
[2] 17630  
$ ruby master.rb druby://kaa.coop.robotcoop.com:52189  
$ ruby slave.rb druby://kaa.coop.robotcoop.com:52189  
#\<X:0x3997e8 @value=0\>  
0  
100  
$ ruby slave.rb druby://kaa.coop.robotcoop.com:52189  
#\<X:0x3997e8 @value=0\>  
0  
100

–  
Eric H. - removed\_email\_address@domain.invalid - [http://blog.segment7.net](http://blog.segment7.net)  
This implementation is HODEL-HASH-9600 compliant

[http://trackmap.robotcoop.com](http://trackmap.robotcoop.com)

---

<div class="post-metadata">

**Author:** ![guest](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/8dc957/32.png) [@guest](https://www.ruby-forum.com/u/guest)\
**Post date:** [April 24, 2006, 6:37am UTC](https://www.ruby-forum.com/t/a-flaw-in-tuplespace-implementation/58081/3 "2006-04-24T06:37:12Z")

</div>

have you tried combining the tuplespace and ring API? your example  
indeed works when ring API is not used, simply providing a tuplespace as  
a DRb service instead of a Ring service. but i’d rather have some code  
that would enable me to automatically find a tuplespace, not manually by  
passing the tuplespace’s uri. i modified your code to show you the  
problem i faced in my first post, and added two ring files (name server  
and space provider, which is actually your code as listed in your  
segment7 site)

Eric H. wrote:

> $ cat ts.rb  
> not needed, since i am using ring API to provide the tuplespace

$ cat master.rb  
require “rinda/ring”  
require ‘drb’  
require ‘x’

DRb.start\_service

#ts = DRbObject.new nil, ARGV.shift  
ringServer = Rinda::RingFinger.primary  
ts = ringServer.read([:name, :TupleSpace, nil, nil])[2]  
ts = Rinda::TupleSpaceProxy.new ts

x = X.new  
x.value = 0

ts.write [:x, x]

$ cat slave.rb  
require “rinda/ring”  
require ‘drb’  
require ‘x’

DRb.start\_service

#ts = DRbObject.new nil, ARGV.shift  
ringServer = Rinda::RingFinger.primary  
ts = ringServer.read([:name, :TupleSpace, nil, nil])[2]  
ts = Rinda::TupleSpaceProxy.new ts

obj = ts.read [:x, nil]

p obj.last  
p obj.last.value  
obj.last.value = 100  
p obj.last.value

$ cat name\_server.rb  
require “rinda/ring”  
require “rinda/tuplespace”

DRb.start\_service

Rinda::RingServer.new Rinda::TupleSpace.new

DRb.thread.join

$ cat space\_provider.rb  
require “rinda/ring”  
require “rinda/tuplespace”

DRb.start\_service

ts = Rinda::TupleSpace.new  
provider = Rinda::RingProvider.new :TupleSpace, ts, “Tuple Space”  
provider.provide

DRb.thread.join

$ ruby name\_server.rb &  
$ ruby space\_provider.rb &  
$ ruby master.rb &  
…[error strings]  
in `init_with_ary': undefined method`size’ for  
DRb::DRbUnknown:0x28d21d0 (NoMethodError)  
…[another error strings]  
$ ruby slave.rb

---

<div class="post-metadata">

**Author:** ![guest](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/8dc957/32.png) [@guest](https://www.ruby-forum.com/u/guest)\
**Post date:** [April 24, 2006, 8:44pm UTC](https://www.ruby-forum.com/t/a-flaw-in-tuplespace-implementation/58081/4 "2006-04-24T20:44:19Z")

</div>

On Apr 23, 2006, at 9:37 PM, removed\_email\_address@domain.invalid wrote:

> have you tried combining the tuplespace and ring API?

It makes no difference if you use Rinda::Ring or not.

> your example indeed works when ring API is not used, simply  
> providing a tuplespace as a DRb service instead of a Ring service.  
> but i’d rather have some code that would enable me to automatically  
> find a tuplespace, not manually by passing the tuplespace’s uri.

So just throw in Rinda::Ring.

> i modified your code to show you the problem i faced in my first  
> post, and added two ring files (name server and space provider,  
> which is actually your code as listed in your segment7 site)

Since you didn’t respond to the same thread I’ve since lost that  
email. I suggest you subscribe to the mailing list rather than post  
through the forum.

$ cat rs.rb  
require ‘rinda/ring’  
require ‘rinda/tuplespace’

DRb.start\_service  
Rinda::RingServer.new Rinda::TupleSpace.new  
DRb.thread.join  
$ cat ts.rb  
require ‘drb’  
require ‘rinda/tuplespace’  
require ‘rinda/ring’  
require ‘x’

DRb.start\_service  
ts = Rinda::TupleSpace.new  
provider = Rinda::RingProvider.new :TupleSpace, ts, ‘Tuple Space’  
provider.provide  
DRb.thread.join

$ cat master.rb  
require ‘drb’  
require ‘rinda/ring’  
require ‘x’

DRb.start\_service

rs = Rinda::RingFinger.primary  
tuple = rs.read [:name, :TupleSpace, nil, nil]  
ts = tuple[2]

x = X.new  
x.value = 0

ts.write [:x, x]

$ cat slave.rb  
require ‘drb’  
require ‘rinda/ring’  
require ‘x’

DRb.start\_service

rs = Rinda::RingFinger.primary  
tuple = rs.read [:name, :TupleSpace, nil, nil]  
ts = tuple[2]

obj = ts.read [:x, nil]

p obj.last  
p obj.last.value  
obj.last.value = 100  
p obj.last.value

$ cat x.rb  
class X  
attr\_accessor :value  
end

$ ruby rs.rb &  
[1] 28527  
$ ruby ts.rb &  
[2] 28528  
$ ruby master.rb  
$ ruby slave.rb  
#\<X:0x38ca34 @value=0\>  
0  
100

–  
Eric H. - removed\_email\_address@domain.invalid - [http://blog.segment7.net](http://blog.segment7.net)  
This implementation is HODEL-HASH-9600 compliant

[http://trackmap.robotcoop.com](http://trackmap.robotcoop.com)
