Class: PPipe::Message

Inherits:
Object show all
Defined in:
lib/parallelpipes.rb

Overview

Quick Links: PPipe, parallelpipes.rb, PPipe::Methods, PPipe::Controller, PPipe::Message

A Message object is designed to make the syntax of receiving messages as beautiful and Ruby-esque as possible. It stores the label, contents and options of the message. At all times it tries to ‘be’ its contents, except if you want specific information out of it, like the label, options, pipe it was sent from (fp) or thread it was sent from (ft).

NB: as well as defining the following methods (see below for their documentation):

tp, tps, tp=, pop_tps # tp means ‘to pipe(s)’

Message also dynamically defines 12 other methods, with very similar meanings.

ep, eps, ep=, pop_eps # ep means ‘exclude pipe(s)’ tt, tts, tt=, pop_tts # tt means ‘to thread(s)’ et, ets, et=, pop_ets # et means ‘exclude thread(s)’

Footnote:

tp, ep, tt and et make up the Message’s address. A message can be given an address before it can be sent. (Although if it has no address this is not an error, as it will be sent to every pipe and every process - see Methods#i_send). Messages that have been returned by t_recv, w_recv, i_recv, i.e. messages that have arrived at their destination, do not have an address.

Constant Summary collapse

SPLITTER =

Internal use only

"PPipe:::"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(label, contents, options = {}) ⇒ Message

Create a new message. The arguments are identical to those for Methods#i_send



564
565
566
567
568
569
570
571
# File 'lib/parallelpipes.rb', line 564

def initialize(label, contents, options={})
  ArgumentError.check([:label, label, [Symbol, String, Fixnum, NilClass]], [:options, options, [Hash, NilClass]])
  ArgumentError.check(['options[:tp]', options[:tp], [Integer, Fixnum, Array, NilClass]], ['options[:ep]', options[:ep], [Integer, Fixnum, Array, NilClass]], ['options[:tt]', options[:tt], [Integer, Fixnum, Array, NilClass]], ['options[:et]', options[:et], [Integer, Fixnum, Array, NilClass]]) if options
  @label = label
  @contents = contents
  @options = options
  check_ambiguities
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(*args) ⇒ Object

Any other methods (except for object_id) are passed to the message’s contents…

message = PPipe::Message.new(:Winnie_the_Pooh, ‘I like honey’, {})

puts message # I like honey

puts message.inspect # “I like honey”

puts message + ‘ very much’ # I like honey very much

puts message.length # 12

puts message.sub(/honey/, ‘bees’) # I like bees

puts message.class # String

So how do you tell if something is a PPipe::Message? parallelpipes.rb adds a method to Object: Object#is_a_ppipe_message? This method will return false for every object except a Message:

puts message.is_a_ppipe_message? # true

puts message.contents.is_a_ppipe_message? # false



717
718
719
# File 'lib/parallelpipes.rb', line 717

def method_missing(*args)
  @contents.send(*args)
end

Instance Attribute Details

#contentsObject (readonly)

see Methods#i_send



560
561
562
# File 'lib/parallelpipes.rb', line 560

def contents
  @contents
end

#labelObject (readonly)

see Methods#i_send



560
561
562
# File 'lib/parallelpipes.rb', line 560

def label
  @label
end

#optionsObject (readonly)

see Methods#i_send



560
561
562
# File 'lib/parallelpipes.rb', line 560

def options
  @options
end

Class Method Details

.from_transmission(line) ⇒ Object

:nodoc:



728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
# File 'lib/parallelpipes.rb', line 728

def self.from_transmission(line) # :nodoc: 
  packets = line.split(SPLITTER, -1) # in case two lines got stuck together.
  extra = packets.shift # something put into the pipe not by ppipe.
#       raise PPipeFatal.new("extra is #{extra.inspect}, line was #{line.inspect}") unless extra
  if extra == nil # line was "", a new line submitted by the user
    extra = ""
  elsif extra == "" # lines was "PPipe:::[etc]", a ppipe message
    extra = nil
  else # Line was "stuffPPipe:::[etc]", a ppipe message with some stuff in front of it, or "stuff", a line submitted by the user
  end
    
  if packets.size == 1
#         if line =~ /^PPipe:::(?<message>.+$)/ 
#         message = new(*eval($~[:message]))  
    message = new(*eval(packets[0]))
  elsif packets.size == 0
    message = nil
  else
    raise PPipeFatal.new("Corrupted message: stuck together: #{line.inspect}")
  end  
  return extra, message
end

.with_listening_thread(thread) ⇒ Object

:nodoc:



652
653
654
# File 'lib/parallelpipes.rb', line 652

def self.with_listening_thread(thread) # :nodoc:
  new(nil, nil, nil).with_listening_thread(thread)
end

Instance Method Details

#arrived?Boolean

Has the message arrived? (see Methods#i_recv)

Returns:

  • (Boolean)


671
672
673
674
675
# File 'lib/parallelpipes.rb', line 671

def arrived?
#       raise ("This message is not listening for anything: it was not created by i_recv") unless @thread 
  return true unless @thread
  return !@thread.alive?
end

#blockingObject

Was the message sent by Methods#w_send ?



636
637
638
# File 'lib/parallelpipes.rb', line 636

def blocking
  return @options[:blocking] 
end

#fpObject

The number of the pipe the message came from



581
582
583
# File 'lib/parallelpipes.rb', line 581

def fp
return @options[:fp]
end

#ftObject

The id of the thread the message came from



587
588
589
# File 'lib/parallelpipes.rb', line 587

def ft
  return @options[:ft]
end

#is_a_ppipe_message?Boolean

parallelpipes.rb adds a method to Object: Object#is_a_ppipe_message? This method will return false for every object except a Message:

puts message.is_a_ppipe_message? # true

puts message.contents.is_a_ppipe_message? # false

See Message#method_missing for an explanation.

Returns:

  • (Boolean)


648
649
650
# File 'lib/parallelpipes.rb', line 648

def is_a_ppipe_message?
  true
end

#joinObject



687
688
689
690
691
692
# File 'lib/parallelpipes.rb', line 687

def join
  raise ("This message is not listening for anything: it was not created by i_recv") unless @thread 
#       return self unless @thread
  @thread.join
  self
end

#killObject

Stop checking to see if the message has arrived. (see Methods#i_recv)



679
680
681
682
# File 'lib/parallelpipes.rb', line 679

def kill
  raise ("This message is not listening for anything: it was not created by i_recv") unless @thread 
  @thread.kill
end

#pop_tpsObject

Return a list of pipes the message is addressed to (see tps) and delete @options



611
612
# File 'lib/parallelpipes.rb', line 611

def pop_tps
end

#to_transmissionObject

private :SPLITTER



725
726
727
# File 'lib/parallelpipes.rb', line 725

def to_transmission
  return SPLITTER + [@label, @contents, @options].inspect + "\n"
end

#tpObject

The pipe the message is addressed to (@options)



596
597
# File 'lib/parallelpipes.rb', line 596

def tp
end

#tp=(value) ⇒ Object

Set the pipe the message is address to (value can be an Integer or and array of integers)



606
607
# File 'lib/parallelpipes.rb', line 606

def tp=(value)
end

#tpsObject

A list of pipes the message is addressed to (returns @options if @options is an array, and [@options] if it is an integer)



601
602
# File 'lib/parallelpipes.rb', line 601

def tps
end

#with_listening_thread(thread) ⇒ Object

Internal use only



658
659
660
661
662
663
664
665
666
667
# File 'lib/parallelpipes.rb', line 658

def with_listening_thread(thread)
  @thread = Thread.ppipe_new do
    thread.join
    message = thread[:message]
    @contents = message.contents
    @label = message.label
    @options = message.options
  end
  return self
end