1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
# -*- coding: utf-8 -*-
require 'delayer/deferred/error'
require 'thread'
module Delayer::Deferred::Deferredable
module NodeSequence
class Sequence
attr_reader :name
def initialize(name)
@name = name.to_sym
@map = {}
@exceptions = Hash.new(Delayer::Deferred::SequenceError)
end
def add(seq, flow = seq.name)
@map[flow] = seq
self
end
def exception(exc, flow)
@exceptions[flow] = exc
self
end
def pull(flow)
if @map.has_key?(flow.to_sym)
@map[flow.to_sym]
else
raise @exceptions[flow.to_sym], "Invalid sequence flow `#{name}' to `#{flow}'."
end
end
def inspect
"#<#{self.class}: #{name}>"
end
end
FRESH = Sequence.new(:fresh)
CONNECTED = Sequence.new(:connected) # 子がいる、未実行
RESERVED = Sequence.new(:reserved) # 実行キュー待ち
RESERVED_C= Sequence.new(:reserved) # 実行キュー待ち(子がいる)
RUN = Sequence.new(:run) # 実行中
RUN_C = Sequence.new(:run) # 実行中(子がいる)
PASS = Sequence.new(:pass) # パス中
PASS_C = Sequence.new(:pass) # パス中
AWAIT = Sequence.new(:await) # Await中
AWAIT_C = Sequence.new(:await) # Await中(子がいる)
GRAFT = Sequence.new(:graft) # 戻り値がAwaitableの時
GRAFT_C = Sequence.new(:graft) # 戻り値がAwaitableの時(子がいる)
CALL_CHILD= Sequence.new(:call_child) # 完了、子がいる
STOP = Sequence.new(:stop) # 完了、子なし
WAIT = Sequence.new(:wait) # 完了、オブザーバ登録済み
BURST_OUT = Sequence.new(:burst_out) # 完了、オブザーバ登録済み、子追加済み
ROTTEN = Sequence.new(:rotten).freeze # 終了
GENOCIDE = Sequence.new(:genocide).freeze# この地ではかつて大量虐殺があったという。
FRESH
.add(CONNECTED, :get_child)
.add(RESERVED, :reserve)
.add(GENOCIDE).freeze
CONNECTED
.add(RESERVED_C, :reserve)
.exception(Delayer::Deferred::MultipleAssignmentError, :get_child)
.add(GENOCIDE).freeze
RESERVED
.add(RUN, :activate)
.add(RESERVED_C, :get_child)
.add(GENOCIDE).freeze
RESERVED_C
.add(RUN_C, :activate)
.exception(Delayer::Deferred::MultipleAssignmentError, :get_child)
.add(GENOCIDE).freeze
RUN
.add(RUN_C, :get_child)
.add(PASS)
.add(AWAIT, :await)
.add(STOP, :complete)
.add(GENOCIDE).freeze
RUN_C
.add(PASS_C)
.add(AWAIT_C, :await)
.add(CALL_CHILD, :complete)
.exception(Delayer::Deferred::MultipleAssignmentError, :get_child)
.add(GENOCIDE).freeze
PASS
.add(PASS_C, :get_child)
.add(RUN, :resume)
.add(GENOCIDE).freeze
PASS_C
.add(RUN_C, :resume)
.add(GENOCIDE).freeze
AWAIT
.add(RUN, :resume)
.add(AWAIT_C, :get_child)
.add(GENOCIDE).freeze
AWAIT_C
.add(RUN_C, :resume)
.exception(Delayer::Deferred::MultipleAssignmentError, :get_child)
.add(GENOCIDE).freeze
CALL_CHILD
.add(GRAFT_C, :await)
.add(ROTTEN, :called)
.add(GENOCIDE).freeze
GRAFT
.add(STOP, :resume)
.add(GRAFT_C, :get_child)
.add(GENOCIDE).freeze
GRAFT_C
.add(CALL_CHILD, :resume)
.add(GENOCIDE).freeze
STOP
.add(GRAFT, :await)
.add(WAIT, :gaze)
.add(GENOCIDE).freeze
WAIT
.add(BURST_OUT, :get_child)
.add(GENOCIDE).freeze
BURST_OUT
.add(ROTTEN, :called)
.add(GENOCIDE).freeze
SEQUENCE_LOCK = Monitor.new
def sequence
@sequence ||= FRESH
end
# このメソッドはスレッドセーフです
def change_sequence(flow, &block)
SEQUENCE_LOCK.synchronize do
old_seq = sequence
new_seq = @sequence = sequence.pull(flow)
(@seq_logger ||= [old_seq]) << new_seq
if block
result = block.()
on_sequence_changed(old_seq, flow, new_seq)
result
else
on_sequence_changed(old_seq, flow, new_seq)
nil
end
end
end
def on_sequence_changed(old_seq, flow, new_seq)
end
def activated?
![FRESH, CONNECTED, RUN, RUN_C].include?(sequence)
end
def spoiled?
sequence == ROTTEN || sequence == GENOCIDE
end
end
end
|