From e81b38b6d34c1959611fd4cfab6a293b07f199e9 Mon Sep 17 00:00:00 2001 From: gsinclair Date: Tue, 17 Feb 2004 22:29:07 +0000 Subject: [PATCH] * lib/rinda/rinda.rb: added documentation (from Hugh Sasse) * lib/rinda/tuplespace.rb: ditto git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5757 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 2 ++ lib/rinda/rinda.rb | 43 ++++++++++++++++++++++++ lib/rinda/tuplespace.rb | 74 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 116 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2564052797..dce393c04f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -89,6 +89,8 @@ Mon Feb 16 22:22:00 2004 Gavin Sinclair * lib/generator.rb: corrected doc format * lib/rinda/rinda.rb: added documentation (from Hugh Sasse) * lib/rinda/tuplespace.rb: ditto + + [Note: rinda files actually committed Wed Feb 18 07:27:00 2004] Mon Feb 16 20:28:52 2004 Hirokazu Yamamoto diff --git a/lib/rinda/rinda.rb b/lib/rinda/rinda.rb index 273560b1de..a29d776810 100644 --- a/lib/rinda/rinda.rb +++ b/lib/rinda/rinda.rb @@ -1,10 +1,32 @@ +# +# rinda.rb: A Ruby implementation of the Linda distibuted computing paradigm. +# +# Introduction to Linda/rinda? +# +# Why is this library separate from drb? +# +# Example(s) +# +# (See the samples directory in the Ruby distribution, from 1.8.2 onwards.) +# + require 'thread' +# +# A module to implement the Linda programming paradigm in Ruby. +# This is part of +drb+ (dRuby). +# module Rinda 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) @@ -13,14 +35,18 @@ module Rinda 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 + # 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) } @@ -29,6 +55,7 @@ module Rinda end end + # Return the tuple itself -- i.e the Array or hash. def value @tuple end @@ -52,7 +79,13 @@ module Rinda 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?(:[]) @@ -64,11 +97,15 @@ module Rinda return true end + # Alias for #match. def ===(tuple) match(tuple) end end + # + # Documentation? + # class DRbObjectTemplate def initialize(uri=nil, ref=nil) @drb_uri = uri @@ -87,6 +124,9 @@ module Rinda end end + # + # TupleSpaceProxy allows a remote Tuplespace to appear as local. + # class TupleSpaceProxy def initialize(ts) @ts = ts @@ -115,6 +155,9 @@ module Rinda end end + # + # Documentation? + # class SimpleRenewer include DRbUndumped def initialize(sec=180) diff --git a/lib/rinda/tuplespace.rb b/lib/rinda/tuplespace.rb index e538f6b137..d30a5047a8 100644 --- a/lib/rinda/tuplespace.rb +++ b/lib/rinda/tuplespace.rb @@ -1,9 +1,21 @@ +# +# = tuplespace: ??? +# +# Overview of rinda/tuplespace.rb +# +# Example(s) +# + require 'monitor' require 'thread' require 'drb/drb' require 'rinda/rinda' module Rinda + # + # A TupleEntry is a Tuple (i.e. a possible entry in some Tuplespace) + # together with expiry and cancellation data. + # class TupleEntry include DRbUndumped @@ -23,8 +35,13 @@ module Rinda !canceled? && !expired? end + # Return the object which makes up the tuple itself: the Array + # or Hash. def value; @ary.value; end + def canceled?; @cancel; end + + # Has this tuple expired? (true/false). def expired? return true unless @expires return false if @expires > Time.now @@ -34,11 +51,28 @@ module Rinda return @expires < Time.now end + # Reset the expiry data according to the supplied argument. If + # the argument is: + # + # +nil+:: it is set to expire in the far future. + # +false+:: it has epired. + # Numeric:: it will expire in that many seconds. + # + # Otherwise the argument refers to some kind of renewer object + # which will reset its expiry time. def renew(sec_or_renewer) sec, @renewer = get_renewer(sec_or_renewer) @expires = make_expires(sec) end + # Create an expiry time. Called with: + # + # +true+:: the expiry time is the start of 1970 (i.e. expired). + # +nil+:: it is Tue Jan 19 03:14:07 GMT Standard Time 2038 (i.e. when + # UNIX clocks will die) + # + # otherwise it is +sec+ seconds into the + # future. def make_expires(sec=nil) case sec when Numeric @@ -50,19 +84,25 @@ module Rinda end end + # Accessor method for the tuple. def [](key) @ary[key] end + # The size of the tuple. def size @ary.size end + # Create a new tuple from the supplied object (array-like). def make_tuple(ary) Rinda::Tuple.new(ary) end private + # Given +true+, +nil+, or +Numeric+, returns that (suitable input to + # make_epires) and +nil+ (no actual +renewer+), else it return the + # time data from the supplied +renewer+. def get_renewer(it) case it when Numeric, true, nil @@ -77,6 +117,9 @@ module Rinda end end + # + # The same as a TupleEntry but with methods to do matching. + # class TemplateEntry < TupleEntry def initialize(ary, expires=nil) super(ary, expires) @@ -87,15 +130,20 @@ module Rinda @template.match(tuple) end + # An alias for #match. def ===(tuple) match(tuple) end + # Create a new Template from the supplied object. def make_tuple(ary) Rinda::Template.new(ary) end end + # + # Documenation? + # class WaitTemplateEntry < TemplateEntry def initialize(place, ary, expires=nil) super(ary, expires) @@ -126,6 +174,9 @@ module Rinda end end + # + # Documenation? + # class NotifyTemplateEntry < TemplateEntry def initialize(place, event, tuple, expires=nil) ary = [event, Rinda::Template.new(tuple)] @@ -156,40 +207,52 @@ module Rinda end end + # + # TupleBag is an unordered collection of tuples. It is the basis + # of Tuplespace. + # class TupleBag def initialize @hash = {} end + # Add the object to the TupleBag. def push(ary) size = ary.size @hash[size] ||= [] @hash[size].push(ary) end + # Remove the object from the TupleBag. def delete(ary) size = ary.size @hash.fetch(size, []).delete(ary) end + # Finds all tuples that match the template and are alive. def find_all(template) @hash.fetch(template.size, []).find_all do |tuple| tuple.alive? && template.match(tuple) end end + # Finds a template that matches and is alive. def find(template) @hash.fetch(template.size, []).find do |tuple| tuple.alive? && template.match(tuple) end end + # Finds all tuples in the TupleBag which when treated as + # templates, match the supplied tuple and are alive. def find_all_template(tuple) @hash.fetch(tuple.size, []).find_all do |template| template.alive? && template.match(tuple) end end + # Delete tuples which are not alive from the TupleBag. Returns + # the list of tuples so deleted. def delete_unless_alive deleted = [] @hash.keys.each do |size| @@ -207,20 +270,24 @@ module Rinda end end + # + # The Tuplespace manages access to the tuples it contains, + # ensuring mutual exclusion requirments are met. + # class TupleSpace include DRbUndumped include MonitorMixin - def initialize(timeout=60) + def initialize(period=60) super() @bag = TupleBag.new @read_waiter = TupleBag.new @take_waiter = TupleBag.new @notify_waiter = TupleBag.new - @timeout = timeout - @period = timeout * 2 + @period = period @keeper = keeper end + # Put a tuple into the tuplespace. def write(tuple, sec=nil) entry = TupleEntry.new(tuple, sec) synchronize do @@ -244,6 +311,7 @@ module Rinda entry end + # Remove an entry from the Tuplespace. def take(tuple, sec=nil, &block) move(nil, tuple, sec, &block) end