fiber18 1.0.0

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.
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
+