Class: Strand

Inherits:
Object
  • Object
show all
Defined in:
lib/strand.rb,
lib/strand/atc.rb,
lib/strand/condition_variable.rb

Defined Under Namespace

Classes: Atc, ConditionVariable

Constant Summary collapse

@@strands =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ Strand

Create and run a strand.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/strand.rb', line 42

def initialize(&block)

  # Initialize our "fiber local" storage.
  @locals = {}

  # Condition variable for joining.
  @join_cond = ConditionVariable.new

  # Create our fiber.
  @fiber = Fiber.new{ fiber_body(&block) }

  # Add us to the list of living strands.
  @@strands[@fiber] = self

  # Finally start the strand.
  resume
end

Instance Attribute Details

#fiberObject (readonly)

The strand’s underlying fiber.



10
11
12
# File 'lib/strand.rb', line 10

def fiber
  @fiber
end

Class Method Details

.currentObject

Get the currently running strand. Primarily used to access “strand local” variables.



18
19
20
# File 'lib/strand.rb', line 18

def self.current
  @@strands[Fiber.current]
end

.listObject

Return an array of all Strands that are alive.



13
14
15
# File 'lib/strand.rb', line 13

def self.list
  @@strands.values
end

.passObject

Yield the strand, but have EM resume it on the next tick.



35
36
37
38
39
# File 'lib/strand.rb', line 35

def self.pass
  fiber = Fiber.current
  EM.next_tick{ fiber.resume }
  Fiber.yield
end

.sleep(seconds) ⇒ Object

EM/fiber safe sleep.



23
24
25
26
27
# File 'lib/strand.rb', line 23

def self.sleep(seconds)
  fiber = Fiber.current
  EM::Timer.new(seconds){ fiber.resume }
  Fiber.yield
end

.yieldObject

Alias for Fiber.yield.



30
31
32
# File 'lib/strand.rb', line 30

def self.yield
  Fiber.yield
end

Instance Method Details

#[](name) ⇒ Object

Access to “strand local” variables, akin to “thread local” variables.

Strand.new do
  ...
  Strand.current[:connection].send(data)
  ...
end


94
95
96
# File 'lib/strand.rb', line 94

def [](name)
  @locals[name]
end

#[]=(name, value) ⇒ Object

Access to “strand local” variables, akin to “thread local” variables.

Strand.new do
  ...
  Strand.current[:connection] = SomeConnectionClass.new(host, port)
  ...
end


104
105
106
# File 'lib/strand.rb', line 104

def []=(name, value)
  @locals[name] = value
end

#alive?Boolean

Like Thread#alive? or Fiber#alive?

Returns:

  • (Boolean)


77
78
79
# File 'lib/strand.rb', line 77

def alive?
  @fiber.alive?
end

#inspectObject

:nodoc:



108
109
110
# File 'lib/strand.rb', line 108

def inspect #:nodoc:
  "#<Strand:0x%s %s" % [object_id, @fiber == Fiber.current ? "run" : "yielded"]
end

#joinObject

Like Thread#join.

s1 = Strand.new{ Strand.sleep(1) }
s2 = Strand.new{ Strand.sleep(1) }
s1.join
s2.join

Raises:

  • (@exception)


65
66
67
68
69
# File 'lib/strand.rb', line 65

def join
  @join_cond.wait if alive?
  raise @exception if @exception
  true
end

#resumeObject

Like Fiber#resume.



72
73
74
# File 'lib/strand.rb', line 72

def resume
  @fiber.resume
end

#valueObject

Like Thread#value. Implicitly calls #join.

strand = Strand.new{ 1+2 }
strand.value # => 3


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

def value
  join and @value
end