Class Rinda::TupleSpace
In: lib/rinda/tuplespace.rb
Parent: Object

The Tuplespace manages access to the tuples it contains, ensuring mutual exclusion requirements are met.

The sec option for the write, take, move, read and notify methods may either be a number of seconds or a Renewer object.

Methods

Included Modules

DRbUndumped MonitorMixin

Public Class methods

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.

[Source]

     # 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

Public Instance methods

Moves tuple to port.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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

[Source]

     # File lib/rinda/tuplespace.rb, line 478
478:     def take(tuple, sec=nil, &block)
479:       move(nil, tuple, sec, &block)
480:     end

Adds tuple

[Source]

     # 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

Private Instance methods

[Source]

     # File lib/rinda/tuplespace.rb, line 578
578:     def create_entry(tuple, sec)
579:       TupleEntry.new(tuple, sec)
580:     end

Removes dead tuples.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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

[Validate]