strand 0.1.0 → 0.2.0.rc0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG +13 -0
  3. data/Gemfile +3 -15
  4. data/LICENSE.txt +1 -0
  5. data/README.rdoc +12 -19
  6. data/Rakefile +10 -57
  7. data/lib/strand.rb +151 -126
  8. data/lib/strand/atc.rb +1 -1
  9. data/lib/strand/em/condition_variable.rb +57 -0
  10. data/lib/strand/em/mutex.rb +63 -0
  11. data/lib/strand/em/queue.rb +84 -0
  12. data/lib/strand/em/thread.rb +305 -0
  13. data/lib/strand/monitor.rb +193 -0
  14. data/lib/strand/version.rb +3 -0
  15. data/spec/spec_helper.rb +9 -5
  16. data/spec/strand/alive.rb +62 -0
  17. data/spec/strand/condition_variable.rb +10 -0
  18. data/spec/strand/condition_variable/broadcast.rb +61 -0
  19. data/spec/strand/condition_variable/signal.rb +62 -0
  20. data/spec/strand/condition_variable/wait.rb +20 -0
  21. data/spec/strand/current.rb +15 -0
  22. data/spec/strand/exit.rb +148 -0
  23. data/spec/strand/join.rb +60 -0
  24. data/spec/strand/local_storage.rb +98 -0
  25. data/spec/strand/mutex.rb +244 -0
  26. data/spec/strand/pass.rb +9 -0
  27. data/spec/strand/queue.rb +124 -0
  28. data/spec/strand/raise.rb +142 -0
  29. data/spec/strand/run.rb +5 -0
  30. data/spec/strand/shared.rb +14 -0
  31. data/spec/strand/sleep.rb +51 -0
  32. data/spec/strand/status.rb +44 -0
  33. data/spec/strand/stop.rb +58 -0
  34. data/spec/strand/strand.rb +32 -0
  35. data/spec/strand/value.rb +39 -0
  36. data/spec/strand/wakeup.rb +60 -0
  37. data/spec/strand_spec.rb +51 -0
  38. data/spec/support/fixtures.rb +305 -0
  39. data/spec/support/scratch.rb +17 -0
  40. data/spec/thread_spec.rb +20 -0
  41. data/strand.gemspec +23 -0
  42. metadata +72 -58
  43. data/Gemfile.lock +0 -40
  44. data/lib/strand/condition_variable.rb +0 -78
  45. data/spec/condition_variable_spec.rb +0 -82
  46. data/test/helper.rb +0 -30
  47. data/test/test_strand.rb +0 -121
@@ -0,0 +1,17 @@
1
+ module ScratchPad
2
+ def self.clear
3
+ @record = nil
4
+ end
5
+
6
+ def self.record(arg)
7
+ @record = arg
8
+ end
9
+
10
+ def self.<<(arg)
11
+ @record << arg
12
+ end
13
+
14
+ def self.recorded
15
+ @record
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'strand/shared'
3
+
4
+ describe ::Thread do
5
+
6
+ let (:strand_type) { ::Thread }
7
+ let (:strand_exception) { ThreadError }
8
+
9
+ around(:each) do |example|
10
+ ScratchPad.clear
11
+ example.run
12
+ end
13
+
14
+ it "should not be running in event machine" do
15
+ Strand.event_machine?.should be_false
16
+ end
17
+
18
+ include_examples Strand
19
+ end
20
+
data/strand.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'strand/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "strand"
8
+ gem.version = Strand::VERSION
9
+ gem.authors = ["Grant Gardner","Christopher J. Bottaro"]
10
+ gem.email = ["grant@lastweekend.com.au", "cjbottaro@alumni.cs.utexas.edu"]
11
+ gem.description = %q{Get thread-like behavior from fibers using EventMachine.}
12
+ gem.summary = %q{Make fibers behave like threads using EventMachine}
13
+ gem.homepage = "http://rubygems.org/gems/strand"
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.test_files = `git ls-files -- {test,spec}/*`.split($/)
16
+ gem.require_paths = ["lib"]
17
+ gem.licenses = %q{MIT}
18
+
19
+ gem.add_development_dependency 'rspec'
20
+ gem.add_development_dependency 'em-spec'
21
+ gem.add_development_dependency 'rr'
22
+ gem.add_development_dependency 'eventmachine', '~> 0.12.0'
23
+ end
metadata CHANGED
@@ -1,63 +1,52 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strand
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
4
+ version: 0.2.0.rc0
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
+ - Grant Gardner
8
9
  - Christopher J. Bottaro
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2011-08-24 00:00:00.000000000 Z
13
+ date: 2012-12-13 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
- name: bundler
16
- requirement: &70284397102060 !ruby/object:Gem::Requirement
16
+ name: rspec
17
+ requirement: !ruby/object:Gem::Requirement
17
18
  none: false
18
19
  requirements:
19
- - - ~>
20
+ - - ! '>='
20
21
  - !ruby/object:Gem::Version
21
- version: 1.0.0
22
+ version: '0'
22
23
  type: :development
23
24
  prerelease: false
24
- version_requirements: *70284397102060
25
- - !ruby/object:Gem::Dependency
26
- name: em-spec
27
- requirement: &70284397100280 !ruby/object:Gem::Requirement
25
+ version_requirements: !ruby/object:Gem::Requirement
28
26
  none: false
29
27
  requirements:
30
28
  - - ! '>='
31
29
  - !ruby/object:Gem::Version
32
30
  version: '0'
33
- type: :development
34
- prerelease: false
35
- version_requirements: *70284397100280
36
31
  - !ruby/object:Gem::Dependency
37
- name: eventmachine
38
- requirement: &70284397098140 !ruby/object:Gem::Requirement
32
+ name: em-spec
33
+ requirement: !ruby/object:Gem::Requirement
39
34
  none: false
40
35
  requirements:
41
- - - ~>
36
+ - - ! '>='
42
37
  - !ruby/object:Gem::Version
43
- version: 0.12.0
38
+ version: '0'
44
39
  type: :development
45
40
  prerelease: false
46
- version_requirements: *70284397098140
47
- - !ruby/object:Gem::Dependency
48
- name: jeweler
49
- requirement: &70284397153900 !ruby/object:Gem::Requirement
41
+ version_requirements: !ruby/object:Gem::Requirement
50
42
  none: false
51
43
  requirements:
52
- - - ~>
44
+ - - ! '>='
53
45
  - !ruby/object:Gem::Version
54
- version: 1.6.4
55
- type: :development
56
- prerelease: false
57
- version_requirements: *70284397153900
46
+ version: '0'
58
47
  - !ruby/object:Gem::Dependency
59
- name: rcov
60
- requirement: &70284397151160 !ruby/object:Gem::Requirement
48
+ name: rr
49
+ requirement: !ruby/object:Gem::Requirement
61
50
  none: false
62
51
  requirements:
63
52
  - - ! '>='
@@ -65,53 +54,81 @@ dependencies:
65
54
  version: '0'
66
55
  type: :development
67
56
  prerelease: false
68
- version_requirements: *70284397151160
69
- - !ruby/object:Gem::Dependency
70
- name: rr
71
- requirement: &70284397150240 !ruby/object:Gem::Requirement
57
+ version_requirements: !ruby/object:Gem::Requirement
72
58
  none: false
73
59
  requirements:
74
60
  - - ! '>='
75
61
  - !ruby/object:Gem::Version
76
62
  version: '0'
77
- type: :development
78
- prerelease: false
79
- version_requirements: *70284397150240
80
63
  - !ruby/object:Gem::Dependency
81
- name: rspec
82
- requirement: &70284397293200 !ruby/object:Gem::Requirement
64
+ name: eventmachine
65
+ requirement: !ruby/object:Gem::Requirement
83
66
  none: false
84
67
  requirements:
85
- - - ! '>='
68
+ - - ~>
86
69
  - !ruby/object:Gem::Version
87
- version: '0'
70
+ version: 0.12.0
88
71
  type: :development
89
72
  prerelease: false
90
- version_requirements: *70284397293200
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: 0.12.0
91
79
  description: Get thread-like behavior from fibers using EventMachine.
92
- email: cjbottaro@alumni.cs.utexas.edu
80
+ email:
81
+ - grant@lastweekend.com.au
82
+ - cjbottaro@alumni.cs.utexas.edu
93
83
  executables: []
94
84
  extensions: []
95
- extra_rdoc_files:
96
- - LICENSE.txt
97
- - README.rdoc
85
+ extra_rdoc_files: []
98
86
  files:
99
87
  - .document
88
+ - .gitignore
100
89
  - .rspec
90
+ - CHANGELOG
101
91
  - Gemfile
102
- - Gemfile.lock
103
92
  - LICENSE.txt
104
93
  - README.rdoc
105
94
  - Rakefile
106
95
  - VERSION
107
96
  - lib/strand.rb
108
97
  - lib/strand/atc.rb
109
- - lib/strand/condition_variable.rb
110
- - spec/condition_variable_spec.rb
98
+ - lib/strand/em/condition_variable.rb
99
+ - lib/strand/em/mutex.rb
100
+ - lib/strand/em/queue.rb
101
+ - lib/strand/em/thread.rb
102
+ - lib/strand/monitor.rb
103
+ - lib/strand/version.rb
111
104
  - spec/spec_helper.rb
112
- - test/helper.rb
113
- - test/test_strand.rb
114
- homepage: http://github.com/cjbottaro/strand
105
+ - spec/strand/alive.rb
106
+ - spec/strand/condition_variable.rb
107
+ - spec/strand/condition_variable/broadcast.rb
108
+ - spec/strand/condition_variable/signal.rb
109
+ - spec/strand/condition_variable/wait.rb
110
+ - spec/strand/current.rb
111
+ - spec/strand/exit.rb
112
+ - spec/strand/join.rb
113
+ - spec/strand/local_storage.rb
114
+ - spec/strand/mutex.rb
115
+ - spec/strand/pass.rb
116
+ - spec/strand/queue.rb
117
+ - spec/strand/raise.rb
118
+ - spec/strand/run.rb
119
+ - spec/strand/shared.rb
120
+ - spec/strand/sleep.rb
121
+ - spec/strand/status.rb
122
+ - spec/strand/stop.rb
123
+ - spec/strand/strand.rb
124
+ - spec/strand/value.rb
125
+ - spec/strand/wakeup.rb
126
+ - spec/strand_spec.rb
127
+ - spec/support/fixtures.rb
128
+ - spec/support/scratch.rb
129
+ - spec/thread_spec.rb
130
+ - strand.gemspec
131
+ homepage: http://rubygems.org/gems/strand
115
132
  licenses:
116
133
  - MIT
117
134
  post_install_message:
@@ -124,19 +141,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
124
141
  - - ! '>='
125
142
  - !ruby/object:Gem::Version
126
143
  version: '0'
127
- segments:
128
- - 0
129
- hash: -933947513672593859
130
144
  required_rubygems_version: !ruby/object:Gem::Requirement
131
145
  none: false
132
146
  requirements:
133
- - - ! '>='
147
+ - - ! '>'
134
148
  - !ruby/object:Gem::Version
135
- version: '0'
149
+ version: 1.3.1
136
150
  requirements: []
137
151
  rubyforge_project:
138
- rubygems_version: 1.8.7
152
+ rubygems_version: 1.8.24
139
153
  signing_key:
140
154
  specification_version: 3
141
- summary: Make fibers behave like threads using EventMachine.
155
+ summary: Make fibers behave like threads using EventMachine
142
156
  test_files: []
data/Gemfile.lock DELETED
@@ -1,40 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- bacon (1.1.0)
5
- diff-lcs (1.1.2)
6
- em-spec (0.2.5)
7
- bacon
8
- eventmachine
9
- rspec (~> 2.6.0)
10
- test-unit
11
- eventmachine (0.12.10)
12
- git (1.2.5)
13
- jeweler (1.6.4)
14
- bundler (~> 1.0)
15
- git (>= 1.2.5)
16
- rake
17
- rake (0.9.2)
18
- rcov (0.9.9)
19
- rr (1.0.3)
20
- rspec (2.6.0)
21
- rspec-core (~> 2.6.0)
22
- rspec-expectations (~> 2.6.0)
23
- rspec-mocks (~> 2.6.0)
24
- rspec-core (2.6.4)
25
- rspec-expectations (2.6.0)
26
- diff-lcs (~> 1.1.2)
27
- rspec-mocks (2.6.0)
28
- test-unit (2.3.2)
29
-
30
- PLATFORMS
31
- ruby
32
-
33
- DEPENDENCIES
34
- bundler (~> 1.0.0)
35
- em-spec
36
- eventmachine (~> 0.12.0)
37
- jeweler (~> 1.6.4)
38
- rcov
39
- rr
40
- rspec
@@ -1,78 +0,0 @@
1
- class Strand
2
- # Provides for Strands (Fibers) what Ruby's ConditionVariable provides for Threads.
3
- class ConditionVariable
4
-
5
- # Create a new condition variable.
6
- def initialize
7
- @waiters = []
8
- end
9
-
10
- # Wait until signaled. Returns true upon returning.
11
- # x = nil
12
- # cond = Strand::ConditionVariable.new
13
- # Strand.new{ cond.wait; x = 1; cond.signal }
14
- # puts x # => nil
15
- # cond.signal
16
- # cond.wait # => true
17
- # puts x # => 1
18
- # If timeout is a number, then returns false if timed out or true if signaled.
19
- # x = nil
20
- # cond = Strand::ConditionVariable.new
21
- # Strand.new{ cond.wait; x = 1; cond.signal }
22
- # puts x # => nil
23
- # cond.wait(0.01) # => false
24
- # puts x # => nil
25
- def wait(timeout = nil)
26
- # Get the fiber that called us.
27
- fiber = Fiber.current
28
-
29
- # Add the fiber to the list of waiters.
30
- @waiters << fiber
31
-
32
- # Setup the timer if they specified a timeout
33
- timer = EM::Timer.new(timeout){ fiber.resume(:timeout) } if timeout
34
-
35
- # Wait for signal or timeout.
36
- if Fiber.yield == :timeout
37
- # Timeout occurred.
38
-
39
- # Remove from list of waiters.
40
- @waiters.delete(fiber)
41
-
42
- false
43
- else
44
- # Ok we were signaled.
45
-
46
- # Cancel the timer if there is one.
47
- timer.cancel if timer
48
-
49
- true
50
- end
51
-
52
- end
53
-
54
- # Asynchronously resume a fiber waiting on this condition variable.
55
- # The waiter is not resumed immediately, but on the next tick of EM's reactor loop.
56
- # cond = Strand::ConditionVariable.new
57
- # Strand.new{ puts 1; cond.wait; puts 2 }
58
- # puts 3
59
- # cond.signal
60
- # puts 4
61
- # # output is...
62
- # 1
63
- # 3
64
- # 4
65
- # 2
66
- def signal
67
- # If there are no waiters, do nothing.
68
- return if @waiters.empty?
69
-
70
- # Find a waiter to wake up.
71
- waiter = @waiters.shift
72
-
73
- # Resume it on next tick.
74
- EM.next_tick{ waiter.resume }
75
- end
76
-
77
- end
78
- end
@@ -1,82 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Strand::ConditionVariable do
4
- include EM::SpecHelper
5
-
6
- context "calling #wait" do
7
- before(:each) do
8
- @cond = described_class.new
9
- @atc = Atc.new :timeout => 0.01
10
- end
11
- it "should block until signaled" do
12
- em do
13
- Strand.new{ @cond.wait; @atc.signal(1) }
14
- @atc.wait(1).should be_false
15
- @cond.signal
16
- @atc.wait(1).should be_true
17
- done
18
- end
19
- end
20
- it "should block until timed out" do
21
- em do
22
- Strand.new{ @cond.wait(0.02); @atc.signal(1) }
23
- @atc.wait(1).should be_false
24
- @atc.wait(1).should be_true
25
- done
26
- end
27
- end
28
- end
29
-
30
- context "calling #signal" do
31
- context "with no waiters" do
32
- before(:all){ @cond = described_class.new }
33
- it "should not do anything" do
34
- @cond.signal.should be_nil
35
- end
36
- end
37
- context "with a single waiter" do
38
- before(:all) do
39
- @cond = described_class.new
40
- @atc = Atc.new :timeout => 0.01
41
- Strand.new{ @cond.wait; @atc.signal(1) }
42
- end
43
- it "should wake up the waiter" do
44
- em do
45
- @atc.wait(1).should be_false
46
- @cond.signal
47
- @atc.wait(1).should be_true
48
- done
49
- end
50
- end
51
- end
52
- context "with multiple waiters" do
53
- before(:all) do
54
- @cond = described_class.new
55
- @atc = Atc.new :timeout => 0.01
56
- Strand.new{ @cond.wait; @atc.signal(1) }
57
- Strand.new{ @cond.wait; @atc.signal(2) }
58
- end
59
- it "should wake up the first waiter" do
60
- em do
61
- @atc.wait(1).should be_false
62
- @atc.wait(2).should be_false
63
- @cond.signal
64
- @atc.wait(1).should be_true
65
- @atc.wait(2).should be_false
66
- done
67
- end
68
- end
69
- it "then wake up the second waiter" do
70
- em do
71
- @atc.wait(1).should be_true
72
- @atc.wait(2).should be_false
73
- @cond.signal
74
- @atc.wait(1).should be_true
75
- @atc.wait(2).should be_true
76
- done
77
- end
78
- end
79
- end
80
- end
81
-
82
- end