1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
#
# rinda.rb: A Ruby implementation of the Linda distributed computing paradigm.
#
# <i>Introduction to Linda/rinda?</i>
#
# <i>Why is this library separate from <tt>drb</tt>?</i>
#
# <i>Example(s)</i>
#
# (See the samples directory in the Ruby distribution, from 1.8.2 onwards.)
#
require 'drb/drb'
require 'thread'
#
# A module to implement the Linda programming paradigm in Ruby.
# This is part of +drb+ (dRuby).
#
module Rinda
class RindaError < RuntimeError; end
class InvalidHashTupleKey < RindaError; end
class RequestCanceledError < ThreadError; end
class RequestExpiredError < ThreadError; end
#
# A tuple is the elementary object in Rinda programming.
# Tuples may be matched against templates if the tuple and
# the template are the same size.
#
class Tuple
# Initialize a tuple with an Array or a Hash.
def initialize(ary_or_hash)
if Hash === ary_or_hash
init_with_hash(ary_or_hash)
else
init_with_ary(ary_or_hash)
end
end
# The number of elements in the tuple.
def size
@tuple.size
end
# Accessor method for elements of the tuple.
def [](k)
@tuple[k]
end
def fetch(k)
@tuple.fetch(k)
end
# Iterate through the tuple, yielding the index or key, and the
# value, thus ensuring arrays are iterated similarly to hashes.
def each # FIXME
if Hash === @tuple
@tuple.each { |k, v| yield(k, v) }
else
@tuple.each_with_index { |v, k| yield(k, v) }
end
end
# Return the tuple itself -- i.e the Array or hash.
def value
@tuple
end
private
def init_with_ary(ary)
@tuple_size = ary.size
@tuple = Array.new(@tuple_size)
@tuple.size.times do |i|
@tuple[i] = ary[i]
end
end
def init_with_hash(hash)
@tuple_size = hash[:size]
@tuple = Hash.new
hash.each do |k, v|
next if k == :size
raise InvalidHashTupleKey unless String === k
@tuple[k] = v
end
end
end
#
# Templates are used to match tuples in Rinda.
#
class Template < Tuple
# Perform the matching of a tuple against a template. An
# element with a +nil+ value in a template acts as a wildcard,
# matching any value in the corresponding position in the tuple.
def match(tuple)
return false unless tuple.respond_to?(:size)
return false unless tuple.respond_to?(:fetch)
return false if @tuple_size && (@tuple_size != tuple.size)
each do |k, v|
begin
it = tuple.fetch(k)
rescue
return false
end
next if v.nil?
next if v == it
next if v === it
return false
end
return true
end
# Alias for #match.
def ===(tuple)
match(tuple)
end
end
#
# <i>Documentation?</i>
#
class DRbObjectTemplate
def initialize(uri=nil, ref=nil)
@drb_uri = uri
@drb_ref = ref
end
def ===(ro)
return true if super(ro)
unless @drb_uri.nil?
return false unless (@drb_uri === ro.__drburi rescue false)
end
unless @drb_ref.nil?
return false unless (@drb_ref === ro.__drbref rescue false)
end
true
end
end
#
# TupleSpaceProxy allows a remote Tuplespace to appear as local.
#
class TupleSpaceProxy
def initialize(ts)
@ts = ts
end
def write(tuple, sec=nil)
@ts.write(tuple, sec)
end
def take(tuple, sec=nil, &block)
port = []
@ts.move(DRbObject.new(port), tuple, sec, &block)
port[0]
end
def read(tuple, sec=nil, &block)
@ts.read(tuple, sec, &block)
end
def read_all(tuple)
@ts.read_all(tuple)
end
def notify(ev, tuple, sec=nil)
@ts.notify(ev, tuple, sec)
end
end
#
# <i>Documentation?</i>
#
class SimpleRenewer
include DRbUndumped
def initialize(sec=180)
@sec = sec
end
def renew
@sec
end
end
end
|