ruck 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,116 @@
1
+
2
+ require "ruck"
3
+
4
+ include Ruck
5
+
6
+ describe Shred do
7
+ context "when calling call" do
8
+ it "should execute the given block" do
9
+ $ran = false
10
+ @shred = Shred.new { $ran = true }
11
+ @shred.call
12
+ $ran.should == true
13
+ end
14
+
15
+ it "should resume execution" do
16
+ $ran = 0
17
+
18
+ @shred = Shred.new do
19
+ $ran = 1
20
+ Shred.current.pause
21
+ $ran = 2
22
+ end
23
+
24
+ @shred.call
25
+ $ran.should == 1
26
+ @shred.call
27
+ $ran.should == 2
28
+ end
29
+
30
+ it "should not mind if you run it too many times" do
31
+ @shred = Shred.new { }
32
+ @shred.call
33
+ @shred.call
34
+ end
35
+
36
+ it "should not let you pause the wrong shred" do
37
+ @shred1 = Shred.new do
38
+ @shred2.call
39
+ end
40
+ @shred2 = Shred.new do
41
+ @shred1.pause
42
+ $shred2_ran = true
43
+ end
44
+
45
+ $shred2_ran = false
46
+ @shred1.call
47
+ $shred2_ran.should be_true
48
+ end
49
+
50
+ it "should let you use [] instead of #call" do
51
+ $ran = false
52
+ @shred = Shred.new { $ran = true }
53
+ @shred[]
54
+ $ran.should == true
55
+ end
56
+ end
57
+
58
+ context "when killing" do
59
+ it "should not resume the next time you call it" do
60
+ $ran = 0
61
+
62
+ @shred = Shred.new do
63
+ $ran = 1
64
+ Shred.current.pause
65
+ $ran = 2
66
+ end
67
+
68
+ @shred.call
69
+ $ran.should == 1
70
+ @shred.kill
71
+ @shred.call
72
+ $ran.should == 1
73
+ end
74
+ end
75
+
76
+ context "when checking finished? and running?" do
77
+ it "finished? should be false just after creation" do
78
+ @shred = Shred.new { }
79
+ @shred.finished?.should be_false
80
+ @shred.running?.should be_true
81
+ end
82
+
83
+ it "finished? should be true just after executing the shred for the last time" do
84
+ pending "not yet supported in Ruby 1.9 because Fiber#alive? is missing"
85
+ @shred = Shred.new { }
86
+ @shred.call
87
+ @shred.finished?.should be_true
88
+ @shred.running?.should be_false
89
+ end
90
+
91
+ it "finished? should be true just after killing the shred" do
92
+ @shred = Shred.new { }
93
+ @shred.kill
94
+ @shred.finished?.should be_true
95
+ @shred.running?.should be_false
96
+ end
97
+ end
98
+
99
+ context "when calling a shred from a shred" do
100
+ it "should update Shred.current appropriately when the inner shred returns" do
101
+ @shred1 = Shred.new do
102
+ Shred.current.should == @shred1
103
+ @shred2.call
104
+ Shred.current.should == @shred1
105
+ end
106
+ @shred2 = Shred.new do
107
+ Shred.current.should == @shred2
108
+ $shred2_ran = true
109
+ end
110
+
111
+ $shred2_ran = false
112
+ @shred1.call
113
+ $shred2_ran.should be_true
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,200 @@
1
+
2
+ require "ruck"
3
+
4
+ include Ruck
5
+
6
+ class MockShred
7
+ def self.next_name
8
+ @@next_name ||= "a"
9
+ name = @@next_name
10
+ @@next_name = @@next_name.succ
11
+ name
12
+ end
13
+
14
+ def initialize(runs_until_finished = 1, shreduler = nil)
15
+ @name = MockShred.next_name
16
+ @finished = false
17
+ @runs_until_finished = runs_until_finished
18
+ @shreduler = shreduler
19
+ end
20
+
21
+ def inspect
22
+ "MockShred<#{@name}>"
23
+ end
24
+
25
+ def call
26
+ $runs << self
27
+ @runs_until_finished -= 1
28
+ @finished = (@runs_until_finished == 0)
29
+ @shreduler.shredule(self) unless @finished || @shreduler == nil
30
+ end
31
+
32
+ def finished?
33
+ @finished
34
+ end
35
+ end
36
+
37
+ describe Shreduler do
38
+ before(:each) do
39
+ @shreduler = Shreduler.new
40
+ $runs = []
41
+ end
42
+
43
+ context "when calling run" do
44
+ # this is internal behavior, but should be tested as run_one is an important override point
45
+ it "should run the shred with run_one" do
46
+ @shreduler.should_receive(:run_one)
47
+ @shreduler.run
48
+ end
49
+
50
+ context "with one shred" do
51
+ it "should run it" do
52
+ @shred = MockShred.new
53
+ @shreduler.shredule(@shred)
54
+ @shreduler.run
55
+ $runs.should == [@shred]
56
+ end
57
+
58
+ it "should end up at the shred's shreduled time" do
59
+ @shred = MockShred.new
60
+ @shreduler.shredule(@shred, 3)
61
+ @shreduler.run
62
+ @shreduler.now.should == 3
63
+ end
64
+ end
65
+
66
+ context "with multiple shreds" do
67
+ it "should run them in order if shreduled in order" do
68
+ @shreds = [MockShred.new, MockShred.new]
69
+ @shreduler.shredule(@shreds[0], 0)
70
+ @shreduler.shredule(@shreds[1], 1)
71
+ @shreduler.run
72
+
73
+ $runs.should == [@shreds[0], @shreds[1]]
74
+ end
75
+
76
+ it "should run them in order if shreduled out of order" do
77
+ @shreds = [MockShred.new, MockShred.new]
78
+ @shreduler.shredule(@shreds[1], 1)
79
+ @shreduler.shredule(@shreds[0], 0)
80
+ @shreduler.run
81
+
82
+ $runs.should == [@shreds[0], @shreds[1]]
83
+ end
84
+
85
+ it "should run them until they are finished" do
86
+ @shred = MockShred.new(5, @shreduler)
87
+ @shreduler.shredule(@shred, 0)
88
+ @shreduler.run
89
+
90
+ $runs.should == (1..5).map { @shred }
91
+ end
92
+ end
93
+ end
94
+
95
+ context "when calling run_one" do
96
+ it "should only run one shred" do
97
+ @shreds = [MockShred.new, MockShred.new]
98
+ @shreduler.shredule(@shreds[1], 1)
99
+ @shreduler.shredule(@shreds[0], 0)
100
+ @shreduler.run_one
101
+
102
+ $runs.should == [@shreds[0]]
103
+ end
104
+
105
+ # fast_forward is protected, but a crucial override point, so should be tested
106
+ it "should call fast_forward before executing the shred" do
107
+ $runs_when_fast_forward_triggered = nil
108
+
109
+ @shreds = [MockShred.new]
110
+ @shreduler.shredule(@shreds[0], 1)
111
+ @shreduler.should_receive(:fast_forward).with(1).and_return { $runs_when_fast_forward_triggered = $runs.dup; nil }
112
+ @shreduler.run_one
113
+
114
+ $runs_when_fast_forward_triggered.should == []
115
+ end
116
+ end
117
+
118
+ context "when unshreduling" do
119
+ it "should work" do
120
+ @shred = MockShred.new
121
+ @shreduler.shredule(@shred)
122
+ @shreduler.unshredule(@shred)
123
+ @shreduler.run
124
+ $runs.should == []
125
+ end
126
+ end
127
+
128
+ context "when convenient" do
129
+ before(:each) do
130
+ @shreduler = Shreduler.new
131
+ @shreduler.make_convenient
132
+ end
133
+
134
+ context "when scheduling with spork" do
135
+ it "should let you schedule with spork" do
136
+ $ran = false
137
+ spork { $ran = true }
138
+ @shreduler.run
139
+ $ran.should be_true
140
+ end
141
+ end
142
+
143
+ context "when scheduling with spork_loop" do
144
+ it "should let you schedule a looping shred with spork_loop" do
145
+ $ran = 0
146
+ spork_loop do
147
+ $ran += 1
148
+ if $ran == 3
149
+ Shred.current.kill
150
+ else
151
+ Shred.yield(1)
152
+ end
153
+ end
154
+
155
+ @shreduler.run
156
+ $ran.should == 3
157
+ end
158
+
159
+ it "should let you specify an amount to automatically yield after before run" do
160
+ $ran = 0
161
+ spork_loop(1) do
162
+ $ran += 1
163
+ Shred.current.kill if $ran == 3
164
+ end
165
+
166
+ @shreduler.run
167
+ $ran.should == 3
168
+ @shreduler.now.should == 3
169
+ end
170
+ end
171
+
172
+ context "when waiting on events" do
173
+ it "should let you wait with Shred.wait_on" do
174
+ $ran = false
175
+ spork do
176
+ Shred.wait_on(:booger)
177
+ $ran = true
178
+ end
179
+ @shreduler.run
180
+ $ran.should be_false
181
+ @shreduler.raise_all(:booger)
182
+ @shreduler.run
183
+ $ran.should be_true
184
+ end
185
+
186
+ it "should let you raise an event with raise_event" do
187
+ $ran = false
188
+ spork do
189
+ Shred.wait_on(:booger)
190
+ $ran = true
191
+ end
192
+ @shreduler.run
193
+ $ran.should be_false
194
+ raise_event(:booger)
195
+ @shreduler.run
196
+ $ran.should be_true
197
+ end
198
+ end
199
+ end
200
+ end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruck
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 19
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 2
8
+ - 3
8
9
  - 0
9
- version: 0.2.0
10
+ version: 0.3.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Tom Lieber
@@ -14,26 +15,58 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-07-10 00:00:00 -07:00
18
+ date: 2010-08-15 00:00:00 -07:00
18
19
  default_executable:
19
- dependencies: []
20
-
21
- description: " Ruck uses continuations and a simple scheduler to ensure \"shreds\"\n (Ruck threads) are woken at precisely the right time according\n to its virtual clock. Schedulers can map virtual time to samples\n in a WAV file, real time, time in a MIDI file, or anything else\n by overriding \"sim_to\" in the Shreduler class.\n"
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: PriorityQueue
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: " Ruck uses continuations and a simple scheduler to ensure \"shreds\"\n (Ruck threads) are woken at precisely the right time according\n to its virtual clock. Schedulers can map virtual time to samples\n in a WAV file, real time, time in a MIDI file, or anything else\n by overriding \"sim_to\" in the Shreduler class.\n \n A small library of useful unit generators and plenty of examples\n are provided. See the README or the web page for details.\n"
22
36
  email: tom@alltom.com
23
37
  executables: []
24
38
 
25
39
  extensions: []
26
40
 
27
41
  extra_rdoc_files:
28
- - README
42
+ - LICENSE
43
+ - README.markdown
29
44
  files:
30
45
  - .gitignore
31
- - README
46
+ - LICENSE
47
+ - README.markdown
32
48
  - Rakefile
33
49
  - VERSION
50
+ - examples/ex01.rb
51
+ - examples/ex02.rb
52
+ - examples/ex03.rb
53
+ - examples/ex04.rb
54
+ - examples/ex05.rb
55
+ - examples/ex06.rb
56
+ - examples/space/media/Beep.wav
57
+ - examples/space/media/Space.png
58
+ - examples/space/media/Star.png
59
+ - examples/space/media/Starfighter.bmp
60
+ - examples/space/space.rb
34
61
  - lib/ruck.rb
35
- - lib/ruck/shreduling.rb
62
+ - lib/ruck/clock.rb
63
+ - lib/ruck/event_clock.rb
64
+ - lib/ruck/shred.rb
65
+ - lib/ruck/shreduler.rb
36
66
  - ruck.gemspec
67
+ - spec/clock_spec.rb
68
+ - spec/shred_spec.rb
69
+ - spec/shreduler_spec.rb
37
70
  has_rdoc: true
38
71
  homepage: http://github.com/alltom/ruck
39
72
  licenses: []
@@ -44,25 +77,38 @@ rdoc_options:
44
77
  require_paths:
45
78
  - lib
46
79
  required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
47
81
  requirements:
48
82
  - - ">="
49
83
  - !ruby/object:Gem::Version
84
+ hash: 3
50
85
  segments:
51
86
  - 0
52
87
  version: "0"
53
88
  required_rubygems_version: !ruby/object:Gem::Requirement
89
+ none: false
54
90
  requirements:
55
91
  - - ">="
56
92
  - !ruby/object:Gem::Version
93
+ hash: 3
57
94
  segments:
58
95
  - 0
59
96
  version: "0"
60
97
  requirements: []
61
98
 
62
99
  rubyforge_project:
63
- rubygems_version: 1.3.6
100
+ rubygems_version: 1.3.7
64
101
  signing_key:
65
102
  specification_version: 3
66
103
  summary: "strong timing for Ruby: cooperative threads on a virtual clock"
67
- test_files: []
68
-
104
+ test_files:
105
+ - spec/clock_spec.rb
106
+ - spec/shred_spec.rb
107
+ - spec/shreduler_spec.rb
108
+ - examples/ex01.rb
109
+ - examples/ex02.rb
110
+ - examples/ex03.rb
111
+ - examples/ex04.rb
112
+ - examples/ex05.rb
113
+ - examples/ex06.rb
114
+ - examples/space/space.rb
data/README DELETED
@@ -1,48 +0,0 @@
1
- A port of ChucK's strong timing to Ruby!
2
-
3
- ruck lets you easily create a virtual clock against
4
- which precise timing of execution can be guaranteed. The
5
- virtual clock can be kept roughly in sync with real time
6
- if you want it to, but you don't have to. For example, in
7
- ChucK, even if your scripts take too long to generate
8
- samples in real time, the audio stream isn't compromised
9
- because it's timed against the virtual clock.
10
-
11
- ruck provides an easily extended scheduler for non-preemptive
12
- shreds (threads) implemented using continuations.
13
- Cooperatively scheduled threads usually don't require
14
- synchronization since execution is never interrupted.
15
-
16
- A few example shredulers (schedulers) are provided:
17
-
18
- UGenShreduler:
19
-
20
- Recently moved to its own gem: ruck-ugen
21
-
22
- RealTimeShreduler
23
-
24
- Recently moved to its own gem: ruck-realtime
25
-
26
- MIDIShreduler
27
-
28
- Recently moved to its own gem: ruck-midi
29
-
30
- GLAppShreduler
31
-
32
- You don't want to know. But see ruck-glapp if you do.
33
-
34
- USAGE
35
- =====
36
-
37
- This project has tons of examples because even though the library
38
- is tiny, there's a lot to test, and a lot of ways to use it.
39
-
40
- For examples of how to implement your own Shreduler, see the bottom
41
- of lib/ruck/shreduling.rb and all the scripts in bin/.
42
-
43
- For example of how to use the provided Shredulers, check the
44
- examples/ directory. Those scripts contain no boilerplate includes
45
- because they are written to be invoked on the command line by
46
- one of the bin/ scripts. For example:
47
-
48
- $ ruck_ugen examples/ugen/ex01.rb