ruck 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,135 +0,0 @@
1
-
2
- module Ruck
3
-
4
- class Shred
5
- attr_accessor :now
6
- attr_accessor :finished
7
- attr_accessor :name
8
-
9
- def initialize(shreduler, now, name, &block)
10
- @shreduler = shreduler
11
- @now = now
12
- @name = name
13
- @block = block
14
- @finished = false
15
- end
16
-
17
- def go(resume)
18
- @resume = resume
19
-
20
- # TODO
21
- # I don't think this is the right place to catch errors.
22
- # I've read the strangest memory errors after an exception
23
- # is caught here; I have a feeling exceptions ought to be
24
- # caught within the continuation itself.
25
- begin
26
- @block.call self
27
- rescue => e
28
- LOG.error "#{self} exited uncleanly:\n#{e}\n#{e.backtrace}"
29
- end
30
-
31
- @finished = true
32
- @shreduler.remove_shred self
33
- end
34
-
35
- def yield(samples)
36
- LOG.debug "shred #{self} yielding #{samples}"
37
- @now += samples
38
- callcc do |cont|
39
- @block = cont # save where we are
40
- @resume.call # jump back to shreduler
41
- end
42
- samples
43
- end
44
-
45
- def finish
46
- @finished = true
47
- @shreduler.remove_shred self
48
-
49
- if @shreduler.current_shred == self
50
- @resume.call # last save point
51
- end
52
- end
53
-
54
- # shreds sort in order of position in time
55
- def <=>(shred)
56
- @now <=> shred.now
57
- end
58
-
59
- def to_s
60
- "<Shred: #{@name}>"
61
- end
62
- end
63
-
64
- class Shreduler
65
- attr_reader :running
66
- attr_reader :current_shred
67
- attr_reader :shreds
68
- attr_reader :now
69
-
70
- def initialize
71
- @shreds = []
72
- @now = 0
73
- @running = false
74
- end
75
-
76
- def spork(name = "", &shred_block)
77
- shred = Shred.new(self, @now, name, &shred_block)
78
- LOG.debug "Adding shred \"#{shred.name}\" at #{@now}"
79
- @shreds << shred
80
- shred
81
- end
82
-
83
- def remove_shred(shred)
84
- LOG.debug "Removing shred \"#{shred.name}\" at #{@now}"
85
- @shreds.delete shred
86
- end
87
-
88
- def next_shred
89
- @shreds.min # furthest behind (Shred#<=> uses Shred's current time)
90
- end
91
-
92
- # called when shreds allow time to pass
93
- # a convenient method to override
94
- def sim_to(new_now)
95
- @now = new_now
96
- end
97
-
98
- def invoke_shred(shred)
99
- # execute shred, saving this as the resume point
100
- LOG.debug "resuming shred #{@current_shred} at #{now}"
101
- @current_shred = shred
102
- callcc { |cont| @current_shred.go(cont) }
103
- LOG.debug "back to run loop"
104
- end
105
-
106
- # invokes the next shred, simulates to the new VM time, then returns
107
- def run_one
108
- shred = next_shred
109
-
110
- sim_to(shred.now)
111
-
112
- invoke_shred(shred)
113
-
114
- if @current_shred.finished
115
- LOG.debug "#{shred} finished"
116
- remove_shred(shred)
117
- end
118
- end
119
-
120
- # ruck main loop
121
- # executes all shreds and synthesizes audio
122
- # until all shreds exit
123
- def run
124
- LOG.debug "shreduler starting"
125
- @running = true
126
-
127
- while @shreds.length > 0
128
- run_one
129
- end
130
-
131
- @running = false
132
- end
133
- end
134
-
135
- end