fiber18 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ pkg/*
data/README ADDED
@@ -0,0 +1,21 @@
1
+ Poor Man's Fiber (API compatible Thread based Fiber implementation for Ruby 1.8)
2
+ (c) 2008 Aman Gupta (tmm1)
3
+
4
+ == Usage
5
+
6
+ f = Fiber.new{ |sym|
7
+ p(sym)
8
+ puts 'hi'
9
+ p(Fiber.yield 1)
10
+ puts 'bye'
11
+ :end
12
+ }
13
+ p(f.resume :begin)
14
+ p(f.resume 2)
15
+
16
+ :begin
17
+ hi
18
+ 1
19
+ 2
20
+ bye
21
+ :end
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ task :test do
2
+ # sh 'ruby -Ilib -rfiber18 test/test_fiber.rb'
3
+ $:.unshift 'lib'
4
+ require 'fiber18'
5
+ require 'test/test_fiber'
6
+ end
7
+
8
+ task :default => :test
data/fiber18.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "fiber18"
6
+ s.version = "1.0.0"
7
+ s.authors = [""]
8
+ s.email = [""]
9
+ s.homepage = "http://github.com/tmm1/fiber18"
10
+ s.summary = %q{API compatible Thread based Fiber implementation for Ruby 1.8}
11
+ s.description = %q{API compatible Thread based Fiber implementation for Ruby 1.8 (including JRuby in 1.8 mode)}
12
+
13
+ s.rubyforge_project = "fiber18"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+ end
File without changes
File without changes
data/lib/fiber18.rb ADDED
@@ -0,0 +1,96 @@
1
+ # Poor Man's Fiber (API compatible Thread based Fiber implementation for Ruby 1.8)
2
+ # (c) 2008 Aman Gupta (tmm1)
3
+
4
+ unless defined? Fiber
5
+ $:.unshift File.expand_path(File.dirname(__FILE__)) + '/compat'
6
+ require 'thread'
7
+
8
+ class FiberError < StandardError; end
9
+
10
+ class Fiber
11
+ def initialize
12
+ raise ArgumentError, 'new Fiber requires a block' unless block_given?
13
+
14
+ @yield = Queue.new
15
+ @resume = Queue.new
16
+
17
+ @thread = Thread.new{ @yield.push [yield(*@resume.pop)] }
18
+ @thread.abort_on_exception = true
19
+ @thread[:fiber] = self
20
+ end
21
+ attr_reader :thread
22
+
23
+ def resume *args
24
+ raise FiberError, 'dead fiber called' unless @thread.alive?
25
+ @resume.push(args)
26
+ result = @yield.pop
27
+ result.size > 1 ? result : result.first
28
+ end
29
+
30
+ def yield *args
31
+ @yield.push(args)
32
+ result = @resume.pop
33
+ result.size > 1 ? result : result.first
34
+ end
35
+
36
+ def self.yield *args
37
+ if fiber = Thread.current[:fiber]
38
+ fiber.yield(*args)
39
+ else
40
+ raise FiberError, 'not inside a fiber'
41
+ end
42
+ end
43
+
44
+ def self.current
45
+ if Thread.current == Thread.main
46
+ return Thread.main[:fiber] ||= RootFiber.new
47
+ end
48
+
49
+ Thread.current[:fiber] or raise FiberError, 'not inside a fiber'
50
+ end
51
+
52
+ def inspect
53
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}>"
54
+ end
55
+ end
56
+
57
+ class RootFiber < Fiber
58
+ def initialize
59
+ # XXX: what is a root fiber anyway?
60
+ end
61
+
62
+ def self.yield *args
63
+ raise FiberError, "can't yield from root fiber"
64
+ end
65
+ end
66
+ end
67
+
68
+ if __FILE__ == $0
69
+ f = Fiber.new{ |sym|
70
+ p(sym)
71
+ puts 'hi'
72
+ p(Fiber.yield 1)
73
+ puts 'bye'
74
+ :end
75
+ }
76
+ p(f.resume :begin)
77
+ p(f.resume 2)
78
+ end
79
+
80
+ __END__
81
+
82
+ $ ruby fbr.rb
83
+ :begin
84
+ hi
85
+ 1
86
+ 2
87
+ bye
88
+ :end
89
+
90
+ $ ruby1.9 fbr.rb
91
+ :begin
92
+ hi
93
+ 1
94
+ 2
95
+ bye
96
+ :end
@@ -0,0 +1,165 @@
1
+ require 'test/unit'
2
+ require 'fiber'
3
+ require 'continuation'
4
+
5
+ class TestFiber < Test::Unit::TestCase
6
+ def test_normal
7
+ f = Fiber.current
8
+ assert_equal(:ok2,
9
+ Fiber.new{|e|
10
+ assert_equal(:ok1, e)
11
+ Fiber.yield :ok2
12
+ }.resume(:ok1)
13
+ )
14
+ assert_equal([:a, :b], Fiber.new{|a, b| [a, b]}.resume(:a, :b))
15
+ end
16
+
17
+ def test_term
18
+ assert_equal(:ok, Fiber.new{:ok}.resume)
19
+ assert_equal([:a, :b, :c, :d, :e],
20
+ Fiber.new{
21
+ Fiber.new{
22
+ Fiber.new{
23
+ Fiber.new{
24
+ [:a]
25
+ }.resume + [:b]
26
+ }.resume + [:c]
27
+ }.resume + [:d]
28
+ }.resume + [:e])
29
+ end
30
+
31
+ def test_many_fibers
32
+ max = 10000
33
+ assert_equal(max, max.times{
34
+ Fiber.new{}
35
+ })
36
+ assert_equal(max,
37
+ max.times{|i|
38
+ Fiber.new{
39
+ }.resume
40
+ }
41
+ )
42
+ end
43
+ end
44
+ __END__
45
+
46
+ def test_many_fibers_with_threads
47
+ max = 1000
48
+ @cnt = 0
49
+ (1..100).map{|ti|
50
+ Thread.new{
51
+ max.times{|i|
52
+ Fiber.new{
53
+ @cnt += 1
54
+ }.resume
55
+ }
56
+ }
57
+ }.each{|t|
58
+ t.join
59
+ }
60
+ assert_equal(:ok, :ok)
61
+ end
62
+
63
+ def test_error
64
+ assert_raise(ArgumentError){
65
+ Fiber.new # Fiber without block
66
+ }
67
+ assert_raise(FiberError){
68
+ f = Fiber.new{}
69
+ Thread.new{f.resume}.join # Fiber yielding across thread
70
+ }
71
+ assert_raise(FiberError){
72
+ f = Fiber.new{}
73
+ f.resume
74
+ f.resume
75
+ }
76
+ assert_raise(RuntimeError){
77
+ f = Fiber.new{
78
+ @c = callcc{|c| @c = c}
79
+ }.resume
80
+ @c.call # cross fiber callcc
81
+ }
82
+ assert_raise(RuntimeError){
83
+ Fiber.new{
84
+ raise
85
+ }.resume
86
+ }
87
+ assert_raise(FiberError){
88
+ Fiber.yield
89
+ }
90
+ assert_raise(FiberError){
91
+ fib = Fiber.new{
92
+ fib.resume
93
+ }
94
+ fib.resume
95
+ }
96
+ assert_raise(FiberError){
97
+ fib = Fiber.new{
98
+ Fiber.new{
99
+ fib.resume
100
+ }.resume
101
+ }
102
+ fib.resume
103
+ }
104
+ end
105
+
106
+ def test_return
107
+ assert_raise(LocalJumpError){
108
+ Fiber.new do
109
+ return
110
+ end.resume
111
+ }
112
+ end
113
+
114
+ def test_throw
115
+ assert_raise(ArgumentError){
116
+ Fiber.new do
117
+ throw :a
118
+ end.resume
119
+ }
120
+ end
121
+
122
+ def test_transfer
123
+ ary = []
124
+ f2 = nil
125
+ f1 = Fiber.new{
126
+ ary << f2.transfer(:foo)
127
+ :ok
128
+ }
129
+ f2 = Fiber.new{
130
+ ary << f1.transfer(:baz)
131
+ :ng
132
+ }
133
+ assert_equal(:ok, f1.transfer)
134
+ assert_equal([:baz], ary)
135
+ end
136
+
137
+ def test_tls
138
+ #
139
+ def tvar(var, val)
140
+ old = Thread.current[var]
141
+ begin
142
+ Thread.current[var] = val
143
+ yield
144
+ ensure
145
+ Thread.current[var] = old
146
+ end
147
+ end
148
+
149
+ fb = Fiber.new {
150
+ assert_equal(nil, Thread.current[:v]); tvar(:v, :x) {
151
+ assert_equal(:x, Thread.current[:v]); Fiber.yield
152
+ assert_equal(:x, Thread.current[:v]); }
153
+ assert_equal(nil, Thread.current[:v]); Fiber.yield
154
+ raise # unreachable
155
+ }
156
+
157
+ assert_equal(nil, Thread.current[:v]); tvar(:v,1) {
158
+ assert_equal(1, Thread.current[:v]); tvar(:v,3) {
159
+ assert_equal(3, Thread.current[:v]); fb.resume
160
+ assert_equal(3, Thread.current[:v]); }
161
+ assert_equal(1, Thread.current[:v]); }
162
+ assert_equal(nil, Thread.current[:v]); fb.resume
163
+ assert_equal(nil, Thread.current[:v]);
164
+ end
165
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fiber18
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 1.0.0
6
+ platform: ruby
7
+ authors:
8
+ - ""
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2012-03-07 00:00:00 Z
14
+ dependencies: []
15
+
16
+ description: API compatible Thread based Fiber implementation for Ruby 1.8 (including JRuby in 1.8 mode)
17
+ email:
18
+ - ""
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - .gitignore
27
+ - README
28
+ - Rakefile
29
+ - fiber18.gemspec
30
+ - lib/compat/continuation.rb
31
+ - lib/compat/fiber.rb
32
+ - lib/fiber18.rb
33
+ - test/test_fiber.rb
34
+ homepage: http://github.com/tmm1/fiber18
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options: []
39
+
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ requirements: []
55
+
56
+ rubyforge_project: fiber18
57
+ rubygems_version: 1.8.15
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: API compatible Thread based Fiber implementation for Ruby 1.8
61
+ test_files: []
62
+