Class: Chan

Inherits:
Object
  • Object
show all
Defined in:
lib/chan.rb

Overview

Chan: Bidirectional enumerator (channel) or the chan object like in Golang

Copyright © 2015, T. Yamada under Ruby License (2-clause BSDL or Artistic).

Check LICENSE terms.

Note: MIT License is also applicable if that compresses LICENSE file.

Defined Under Namespace

Classes: Yielder

Constant Summary collapse

VERSION =

VERSION string

'0.0.0.1'

Instance Method Summary collapse

Constructor Details

#initialize(&blk) ⇒ Chan

Constructor. you should pass a block like you do in Enumerator. Actually if you use Enumerator.new{} as external iterator, you can safely convert it to Chan.new{} in most cases.



58
59
60
61
62
63
64
65
66
# File 'lib/chan.rb', line 58

def initialize(&blk)
	@f=Fiber.new{|parent_to_child,child_to_parent,blk|
		ch=Yielder.new(parent_to_child,child_to_parent)
		blk.call(ch)
	}
	@parent_to_child=[]
	@child_to_parent=[]
	@f.resume(@parent_to_child,@child_to_parent,blk)
end

Instance Method Details

#gen_enum(enum) ⇒ Object

Builds an Enumerator using existing Enumerator.



103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/chan.rb', line 103

def gen_enum(enum)
	Enumerator.new{|y|
		begin
			loop{
				self<<enum.next
				y<<self.receive if self.next?
			} # StopIteration is catched by Kernel#loop
		rescue RuntimeError
			# attempted to push to closed Chan
		end
		y<<self.receive while self.next?
	}
end

#next?Boolean

Tells if the channel has next element. If false, it means end of enumeration or you need to give more object.

Returns:

  • (Boolean)


70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/chan.rb', line 70

def next?
	while @child_to_parent.empty?
		begin
			flg=@f.resume
			if flg&&@parent_to_child.empty?
				return false
			end
		rescue FiberError
			return false
		end
	end
	true
end

#peekObject

Receives an object from child without modifying the queue.

Raises:

  • (StopIteration)


84
85
86
87
# File 'lib/chan.rb', line 84

def peek
	raise StopIteration.new('too many read requests') if !next?
	@child_to_parent.first
end

#receiveObject Also known as: next, succ

Receives an object from child. aliased to next/succ.

Raises:

  • (StopIteration)


90
91
92
93
# File 'lib/chan.rb', line 90

def receive
	raise StopIteration.new('too many read requests') if !next?
	@child_to_parent.shift
end

#send(v) ⇒ Object Also known as: <<

Sends an object to child.



97
98
99
# File 'lib/chan.rb', line 97

def send(v)
	@parent_to_child.push(v)
end