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



580
581
582
583
584
585
586
587
# File 'lib/parallelpipes.rb', line 580

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



733
734
735
# File 'lib/parallelpipes.rb', line 733

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

Instance Attribute Details

#contentsObject (readonly)

see Methods#i_send



576
577
578
# File 'lib/parallelpipes.rb', line 576

def contents
  @contents
end

#labelObject (readonly)

see Methods#i_send



576
577
578
# File 'lib/parallelpipes.rb', line 576

def label
  @label
end

#optionsObject (readonly)

see Methods#i_send



576
577
578
# File 'lib/parallelpipes.rb', line 576

def options
  @options
end

Class Method Details

.from_transmission(line) ⇒ Object

:nodoc:



744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
# File 'lib/parallelpipes.rb', line 744

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:



668
669
670
# File 'lib/parallelpipes.rb', line 668

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)


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

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 ?



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

def blocking
	return @options[:blocking]	
end

#fpObject

The number of the pipe the message came from



597
598
599
# File 'lib/parallelpipes.rb', line 597

def fp
return @options[:fp]
end

#ftObject

The id of the thread the message came from



603
604
605
# File 'lib/parallelpipes.rb', line 603

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)


664
665
666
# File 'lib/parallelpipes.rb', line 664

def is_a_ppipe_message?
	true
end

#joinObject



703
704
705
706
707
708
# File 'lib/parallelpipes.rb', line 703

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)



695
696
697
698
# File 'lib/parallelpipes.rb', line 695

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



627
628
# File 'lib/parallelpipes.rb', line 627

def pop_tps
end

#to_transmissionObject

private :SPLITTER



741
742
743
# File 'lib/parallelpipes.rb', line 741

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

#tpObject

The pipe the message is addressed to (@options)



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

def tp
end

#tp=(value) ⇒ Object

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



622
623
# File 'lib/parallelpipes.rb', line 622

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)



617
618
# File 'lib/parallelpipes.rb', line 617

def tps
end

#with_listening_thread(thread) ⇒ Object

Internal use only



674
675
676
677
678
679
680
681
682
683
# File 'lib/parallelpipes.rb', line 674

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