Class | Rinda::TupleSpace |
In: |
lib/rinda/tuplespace.rb
|
Parent: | Object |
Creates a new TupleSpace. period is used to control how often to look for dead tuples after modifications to the TupleSpace.
If no dead tuples are found period seconds after the last modification, the TupleSpace will stop looking for dead tuples.
# File lib/rinda/tuplespace.rb, line 438 438: def initialize(period=60) 439: super() 440: @bag = TupleBag.new 441: @read_waiter = TupleBag.new 442: @take_waiter = TupleBag.new 443: @notify_waiter = TupleBag.new 444: @period = period 445: @keeper = nil 446: end
Moves tuple to port.
# File lib/rinda/tuplespace.rb, line 485 485: def move(port, tuple, sec=nil) 486: template = WaitTemplateEntry.new(self, tuple, sec) 487: yield(template) if block_given? 488: synchronize do 489: entry = @bag.find(template) 490: if entry 491: port.push(entry.value) if port 492: @bag.delete(entry) 493: notify_event('take', entry.value) 494: return entry.value 495: end 496: raise RequestExpiredError if template.expired? 497: 498: begin 499: @take_waiter.push(template) 500: start_keeper if template.expires 501: while true 502: raise RequestCanceledError if template.canceled? 503: raise RequestExpiredError if template.expired? 504: entry = @bag.find(template) 505: if entry 506: port.push(entry.value) if port 507: @bag.delete(entry) 508: notify_event('take', entry.value) 509: return entry.value 510: end 511: template.wait 512: end 513: ensure 514: @take_waiter.delete(template) 515: end 516: end 517: end
Registers for notifications of event. Returns a NotifyTemplateEntry. See NotifyTemplateEntry for examples of how to listen for notifications.
event can be:
‘write’: | A tuple was added |
‘take’: | A tuple was taken or moved |
‘delete’: | A tuple was lost after being overwritten or expiring |
The TupleSpace will also notify you of the ‘close’ event when the NotifyTemplateEntry has expired.
# File lib/rinda/tuplespace.rb, line 568 568: def notify(event, tuple, sec=nil) 569: template = NotifyTemplateEntry.new(self, event, tuple, sec) 570: synchronize do 571: @notify_waiter.push(template) 572: end 573: template 574: end
Reads tuple, but does not remove it.
# File lib/rinda/tuplespace.rb, line 522 522: def read(tuple, sec=nil) 523: template = WaitTemplateEntry.new(self, tuple, sec) 524: yield(template) if block_given? 525: synchronize do 526: entry = @bag.find(template) 527: return entry.value if entry 528: raise RequestExpiredError if template.expired? 529: 530: begin 531: @read_waiter.push(template) 532: start_keeper if template.expires 533: template.wait 534: raise RequestCanceledError if template.canceled? 535: raise RequestExpiredError if template.expired? 536: return template.found 537: ensure 538: @read_waiter.delete(template) 539: end 540: end 541: end
Returns all tuples matching tuple. Does not remove the found tuples.
# File lib/rinda/tuplespace.rb, line 546 546: def read_all(tuple) 547: template = WaitTemplateEntry.new(self, tuple, nil) 548: synchronize do 549: entry = @bag.find_all(template) 550: entry.collect do |e| 551: e.value 552: end 553: end 554: end
Removes tuple
# File lib/rinda/tuplespace.rb, line 478 478: def take(tuple, sec=nil, &block) 479: move(nil, tuple, sec, &block) 480: end
Adds tuple
# File lib/rinda/tuplespace.rb, line 451 451: def write(tuple, sec=nil) 452: entry = create_entry(tuple, sec) 453: synchronize do 454: if entry.expired? 455: @read_waiter.find_all_template(entry).each do |template| 456: template.read(tuple) 457: end 458: notify_event('write', entry.value) 459: notify_event('delete', entry.value) 460: else 461: @bag.push(entry) 462: start_keeper if entry.expires 463: @read_waiter.find_all_template(entry).each do |template| 464: template.read(tuple) 465: end 466: @take_waiter.find_all_template(entry).each do |template| 467: template.signal 468: end 469: notify_event('write', entry.value) 470: end 471: end 472: entry 473: end
# File lib/rinda/tuplespace.rb, line 578 578: def create_entry(tuple, sec) 579: TupleEntry.new(tuple, sec) 580: end
Removes dead tuples.
# File lib/rinda/tuplespace.rb, line 585 585: def keep_clean 586: synchronize do 587: @read_waiter.delete_unless_alive.each do |e| 588: e.signal 589: end 590: @take_waiter.delete_unless_alive.each do |e| 591: e.signal 592: end 593: @notify_waiter.delete_unless_alive.each do |e| 594: e.notify(['close']) 595: end 596: @bag.delete_unless_alive.each do |e| 597: notify_event('delete', e.value) 598: end 599: end 600: end
Checks the tuplespace to see if it needs cleaning.
# File lib/rinda/tuplespace.rb, line 632 632: def need_keeper? 633: return true if @bag.has_expires? 634: return true if @read_waiter.has_expires? 635: return true if @take_waiter.has_expires? 636: return true if @notify_waiter.has_expires? 637: end
Notifies all registered listeners for event of a status change of tuple.
# File lib/rinda/tuplespace.rb, line 606 606: def notify_event(event, tuple) 607: ev = [event, tuple] 608: @notify_waiter.find_all_template(ev).each do |template| 609: template.notify(ev) 610: end 611: end
Creates a thread that scans the tuplespace for expired tuples.
# File lib/rinda/tuplespace.rb, line 616 616: def start_keeper 617: return if @keeper && @keeper.alive? 618: @keeper = Thread.new do 619: while true 620: sleep(@period) 621: synchronize do 622: break unless need_keeper? 623: keep_clean 624: end 625: end 626: end 627: end