blob: 453c9bbef778d5189b27f8403c1be76f6d1f4763 (
plain)
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
|
# -*- coding: utf-8 -*-
class Deferred
include Deferredable
def initialize(follow = nil)
@follow = follow
@backtrace = caller if Mopt.debug
end
alias :deferredable_cancel :cancel
def cancel
deferredable_cancel
@follow.cancel if @follow.is_a? Deferredable end
class << self
# 実行中のDeferredを失敗させる。raiseと違って、Exception以外のオブジェクトをtrap()に渡すことができる。
# Deferredのnextとtrapの中でだけ呼び出すことができる。
# ==== Args
# [value] trap()に渡す値
# ==== Throw
# :__deferredable_fail をthrowする
def fail(value)
throw(:__deferredable_fail, value) end
# 複数のdeferredを引数に取って、それら全ての実行が終了したら、
# その結果を引数の順番通りに格納したArrayを引数に呼ばれるDeferredを返す。
# 引数のDeferredが一つでも失敗するとこのメソッドの返すDeferredも失敗する。
# ==== Args
# [defer] 終了を待つDeferredオブジェクト
# [*follow] 他のDeferredオブジェクト
# ==== Return
# Deferred
def when(defer = nil, *follow)
return deferred{ [] } if defer.nil?
defer.next{ |res|
Deferred.when(*follow).next{ |follow_res|
[res] + follow_res
}
}
end
# Kernel#systemを呼び出して、コマンドが成功たら成功するDeferredを返す。
# 失敗した場合、trap{}ブロックには $? の値(Process::Status)か、例外が発生した場合それが渡される
# ==== Args
# [*args] Kernel#system の引数
# ==== Return
# Deferred
def system(*args)
promise = Deferred.new
Thread.new{
if Kernel.system(*args)
promise.call(true)
else
promise.fail($?) end
}.trap{ |e|
promise.fail(e) }
promise
end
end
end
class Thread
include Deferredable
alias _deferredable_trap initialize
def initialize(*args, &proc)
_deferredable_trap(*args){ |*args|
begin
result = proc.call(*args)
self.call(result)
result
rescue Exception => e
self.fail(e)
end
}
end
alias :deferredable_cancel :cancel
def cancel
deferredable_cancel
kill end
end
module Enumerable
# 遅延each。あとで実行されるし、あんまりループに時間がかかるようなら一旦ループを終了する
def deach(&proc)
iteratee = to_a
iteratee = dup if equal?(iteratee)
deferred{
result = nil
while not iteratee.empty?
item = iteratee.shift
proc.call(item)
if Delayer.expire?
break result = iteratee.deach(&proc) end end
result }
end
end
def deferred(&proc)
Deferred.new.next(&proc) end
# ~> -:4: uninitialized constant Deferred::Deferredable (NameError)
|