thread_variables 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in thread_local_variable_access.gemspec
4
+ gemspec
5
+
6
+ gem "redgreen", :platform => :ruby_18
7
+ gem "ansi", :platform => :ruby_19
8
+ gem "rake", "~> 0.9.2.2"
9
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Stefan Kaes
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # ThreadVariables
2
+
3
+ This gem provides methods to access thread local variables with a ruby trunk compatible
4
+ API. It also provides an implementation for ruby 1.9, since ruby 1.9.3 made thread locals
5
+ fiber local.
6
+
7
+ See http://bugs.ruby-lang.org/issues/7097
8
+
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'thread_variables'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install thread_variables
23
+
24
+ ## Usage
25
+
26
+ require "thread_variables"
27
+ Thread.current.thread_variable_set :foo, 5
28
+ Thread.current.thread_variable_get :foo
29
+ Thread.current.thread_variable? :foo
30
+ Thread.current.thread_variables
31
+
32
+ ## Contributing
33
+
34
+ 1. Fork it
35
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
36
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
37
+ 4. Push to the branch (`git push origin my-new-feature`)
38
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require "bundler/gem_tasks"
2
+ require "bundler/setup"
3
+ require "rake/testtask"
4
+ include Rake::DSL
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList['test/**/*_test.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default do
13
+ Rake::Task[:test].invoke
14
+ end
@@ -0,0 +1,31 @@
1
+ require "thread_variables/version"
2
+ require "thread"
3
+
4
+ class Thread
5
+ if RUBY_VERSION < "1.9"
6
+
7
+ alias :thread_variable_get :[]
8
+ alias :thread_variable_set :[]=
9
+ alias :thread_variables :keys
10
+ alias :thread_variable? :key?
11
+
12
+ elsif !instance_methods.include?(:thread_variables)
13
+
14
+ def thread_variables
15
+ (locals = @locals) ? locals.keys : []
16
+ end
17
+
18
+ def thread_variable?(k)
19
+ (locals = @locals) && locals.include?(k.to_sym)
20
+ end
21
+
22
+ def thread_variable_get(k)
23
+ (locals = @locals) ? locals[k.to_sym] : nil
24
+ end
25
+
26
+ def thread_variable_set(k,v)
27
+ (@locals ||= {})[k.to_sym] = v
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module ThreadVariables
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,26 @@
1
+ # colorized output for Test::Unit / MiniTest
2
+ begin
3
+ if RUBY_VERSION < "1.9"
4
+ require 'redgreen'
5
+ else
6
+ require "test/unit/testcase"
7
+ class MiniTest::Unit::TestCase
8
+ alias :run_without_colors :run
9
+ require 'ansi/code'
10
+ ANSI_COLOR_MAPPING = Hash.new(:white).merge!('.' => :green, 'S' => :magenta, 'F' => :yellow, 'E' => :red )
11
+ def run(*args)
12
+ r = run_without_colors *args
13
+ ANSI.ansi(r, ANSI_COLOR_MAPPING[r])
14
+ end
15
+ end
16
+ class MiniTest::Unit
17
+ def status(io = @@out)
18
+ format = "%d tests, %d assertions, %d failures, %d errors, %d skips"
19
+ color = (errors + failures) > 0 ? :red : :green
20
+ io.puts ANSI.ansi(format % [test_count, assertion_count, failures, errors, skips], color)
21
+ end
22
+ end
23
+ end
24
+ rescue LoadError => e
25
+ # do nothing
26
+ end if $stdout.tty?
@@ -0,0 +1,130 @@
1
+ require 'thread_variables'
2
+ require 'test/unit'
3
+ require File.expand_path('../colorized_test_output', __FILE__)
4
+
5
+ class ThreadVariablesTest < Test::Unit::TestCase
6
+
7
+ def test_symbol_setter_and_getter
8
+ t = Thread.new { Thread.current.thread_variable_set :foo, 42 }
9
+ t.join
10
+ assert_equal 42, t.thread_variable_get(:foo)
11
+ end
12
+
13
+ def test_string_setter_and_getter
14
+ t = Thread.new { Thread.current.thread_variable_set "foo", 42 }
15
+ t.join
16
+ assert_equal 42, t.thread_variable_get("foo")
17
+ end
18
+
19
+ def test_string_setter_and_smybol_getter
20
+ t = Thread.new { Thread.current.thread_variable_set "foo", 42 }
21
+ t.join
22
+ assert_equal 42, t.thread_variable_get(:foo)
23
+ end
24
+
25
+ def test_symbol_setter_and_string_getter
26
+ t = Thread.new { Thread.current.thread_variable_set :foo, 42 }
27
+ t.join
28
+ assert_equal 42, t.thread_variable_get("foo")
29
+ end
30
+
31
+ def test_listing_keys
32
+ t = Thread.new do
33
+ Thread.current.thread_variable_set :foo, 42
34
+ Thread.current.thread_variable_set "bar", 815
35
+ end
36
+ t.join
37
+ vs = t.thread_variables
38
+ assert_equal 2, vs.size
39
+ assert vs.include?(:foo)
40
+ assert vs.include?(:bar)
41
+ end
42
+
43
+ def test_ckecking_keys
44
+ t = Thread.new do
45
+ Thread.current.thread_variable_set :foo, 42
46
+ Thread.current.thread_variable_set "bar", 815
47
+ end
48
+ t.join
49
+ assert t.thread_variable?(:foo)
50
+ assert t.thread_variable?(:bar)
51
+ end
52
+
53
+ # official tests
54
+ # see http://bugs.ruby-lang.org/attachments/3149/thread_variables.patch
55
+
56
+ def test_main_thread_variable_in_enumerator
57
+ assert_equal Thread.main, Thread.current
58
+
59
+ Thread.current.thread_variable_set :foo, "bar"
60
+
61
+ thread, value = Fiber.new {
62
+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)]
63
+ }.resume
64
+
65
+ assert_equal Thread.current, thread
66
+ assert_equal Thread.current.thread_variable_get(:foo), value
67
+ end if RUBY_VERSION >= "1.9"
68
+
69
+ def test_thread_variable_in_enumerator
70
+ Thread.new {
71
+ Thread.current.thread_variable_set :foo, "bar"
72
+
73
+ thread, value = Fiber.new {
74
+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)]
75
+ }.resume
76
+
77
+ assert_equal Thread.current, thread
78
+ assert_equal Thread.current.thread_variable_get(:foo), value
79
+ }.join
80
+ end if RUBY_VERSION >= "1.9"
81
+
82
+ def test_thread_variables
83
+ assert_equal [], Thread.new { Thread.current.thread_variables }.join.value
84
+
85
+ t = Thread.new {
86
+ Thread.current.thread_variable_set(:foo, "bar")
87
+ Thread.current.thread_variables
88
+ }
89
+ assert_equal [:foo], t.join.value
90
+ end
91
+
92
+ def test_thread_variable?
93
+ assert !Thread.new { Thread.current.thread_variable?("foo") }.join.value
94
+ t = Thread.new {
95
+ Thread.current.thread_variable_set("foo", "bar")
96
+ }.join
97
+
98
+ assert t.thread_variable?("foo")
99
+ assert t.thread_variable?(:foo)
100
+ assert !t.thread_variable?(:bar)
101
+ end
102
+
103
+ def test_thread_variable_strings_and_symbols_are_the_same_key
104
+ t = Thread.new {}.join
105
+ t.thread_variable_set("foo", "bar")
106
+ assert_equal "bar", t.thread_variable_get(:foo)
107
+ end
108
+
109
+ def test_thread_variable_frozen
110
+ t = Thread.new { }.join
111
+ t.freeze
112
+ exception_class = RUBY_VERSION < "1.9" ? TypeError : RuntimeError
113
+ assert_raises(exception_class) do
114
+ t.thread_variable_set(:foo, "bar")
115
+ end
116
+ end
117
+
118
+ def test_thread_variable_security
119
+ t = Thread.new { sleep }
120
+
121
+ assert_raises(SecurityError) do
122
+ Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join
123
+ end
124
+
125
+ assert_raises(SecurityError) do
126
+ Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join
127
+ end
128
+ end if RUBY_VERSION > "1.9.3"
129
+
130
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'thread_variables/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "thread_variables"
8
+ gem.version = ThreadVariables::VERSION
9
+ gem.authors = ["Stefan Kaes"]
10
+ gem.email = ["stefan.kaes@xing.com"]
11
+ gem.description = %q{Provide thread local variables for ruby 1.9 and API for all ruby versions}
12
+ gem.summary = %q{Provide functionality compatible to latest trunk commit for all ruby version above 1.8}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,319 @@
1
+ diff --git a/NEWS b/NEWS
2
+ index 0e4508e..b20cebb 100644
3
+ --- a/NEWS
4
+ +++ b/NEWS
5
+ @@ -81,6 +81,16 @@ with all sufficient information, see the ChangeLog file.
6
+ * added Struct#to_h returning values with keys corresponding to the
7
+ instance variable names.
8
+
9
+ + * Thread
10
+ + * added method:
11
+ + * added Thread#thread_variable_get for getting thread local variables
12
+ + (these are different than Fiber local variables).
13
+ + * added Thread#thread_variable_set for setting thread local variables.
14
+ + * added Thread#thread_variables for getting a list of the thread local
15
+ + variable keys.
16
+ + * added Thread#thread_variable? for testing to see if a particular thread
17
+ + variable has been set.
18
+ +
19
+ * Time
20
+ * change return value:
21
+ * Time#to_s returned encoding defaults to US-ASCII but automatically
22
+ diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
23
+ index c8081b4..145e021 100644
24
+ --- a/test/ruby/test_thread.rb
25
+ +++ b/test/ruby/test_thread.rb
26
+ @@ -27,6 +27,79 @@ class TestThread < Test::Unit::TestCase
27
+ end
28
+ end
29
+
30
+ + def test_main_thread_variable_in_enumerator
31
+ + assert_equal Thread.main, Thread.current
32
+ +
33
+ + Thread.current.thread_variable_set :foo, "bar"
34
+ +
35
+ + thread, value = Fiber.new {
36
+ + Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)]
37
+ + }.resume
38
+ +
39
+ + assert_equal Thread.current, thread
40
+ + assert_equal Thread.current.thread_variable_get(:foo), value
41
+ + end
42
+ +
43
+ + def test_thread_variable_in_enumerator
44
+ + Thread.new {
45
+ + Thread.current.thread_variable_set :foo, "bar"
46
+ +
47
+ + thread, value = Fiber.new {
48
+ + Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)]
49
+ + }.resume
50
+ +
51
+ + assert_equal Thread.current, thread
52
+ + assert_equal Thread.current.thread_variable_get(:foo), value
53
+ + }.join
54
+ + end
55
+ +
56
+ + def test_thread_variables
57
+ + assert_equal [], Thread.new { Thread.current.thread_variables }.join.value
58
+ +
59
+ + t = Thread.new {
60
+ + Thread.current.thread_variable_set(:foo, "bar")
61
+ + Thread.current.thread_variables
62
+ + }
63
+ + assert_equal [:foo], t.join.value
64
+ + end
65
+ +
66
+ + def test_thread_variable?
67
+ + refute Thread.new { Thread.current.thread_variable?("foo") }.join.value
68
+ + t = Thread.new {
69
+ + Thread.current.thread_variable_set("foo", "bar")
70
+ + }.join
71
+ +
72
+ + assert t.thread_variable?("foo")
73
+ + assert t.thread_variable?(:foo)
74
+ + refute t.thread_variable?(:bar)
75
+ + end
76
+ +
77
+ + def test_thread_variable_strings_and_symbols_are_the_same_key
78
+ + t = Thread.new {}.join
79
+ + t.thread_variable_set("foo", "bar")
80
+ + assert_equal "bar", t.thread_variable_get(:foo)
81
+ + end
82
+ +
83
+ + def test_thread_variable_frozen
84
+ + t = Thread.new { }.join
85
+ + t.freeze
86
+ + assert_raises(RuntimeError) do
87
+ + t.thread_variable_set(:foo, "bar")
88
+ + end
89
+ + end
90
+ +
91
+ + def test_thread_variable_security
92
+ + t = Thread.new { sleep }
93
+ +
94
+ + assert_raises(SecurityError) do
95
+ + Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join
96
+ + end
97
+ +
98
+ + assert_raises(SecurityError) do
99
+ + Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join
100
+ + end
101
+ + end
102
+ +
103
+ def test_mutex_synchronize
104
+ m = Mutex.new
105
+ r = 0
106
+ diff --git a/thread.c b/thread.c
107
+ index b512566..b21a088 100644
108
+ --- a/thread.c
109
+ +++ b/thread.c
110
+ @@ -2525,6 +2525,9 @@ rb_thread_local_aref(VALUE thread, ID id)
111
+ * #=> nil if fiber-local
112
+ * #=> 2 if thread-local (The value 2 is leaked to outside of meth method.)
113
+ *
114
+ + * For thread-local variables, please see <code>Thread#thread_local_get</code>
115
+ + * and <code>Thread#thread_local_set</code>.
116
+ + *
117
+ */
118
+
119
+ static VALUE
120
+ @@ -2561,7 +2564,9 @@ rb_thread_local_aset(VALUE thread, ID id, VALUE val)
121
+ * thr[sym] = obj -> obj
122
+ *
123
+ * Attribute Assignment---Sets or creates the value of a fiber-local variable,
124
+ - * using either a symbol or a string. See also <code>Thread#[]</code>.
125
+ + * using either a symbol or a string. See also <code>Thread#[]</code>. For
126
+ + * thread-local variables, please see <code>Thread#thread_variable_set</code>
127
+ + * and <code>Thread#thread_variable_get</code>.
128
+ */
129
+
130
+ static VALUE
131
+ @@ -2572,6 +2577,80 @@ rb_thread_aset(VALUE self, VALUE id, VALUE val)
132
+
133
+ /*
134
+ * call-seq:
135
+ + * thr.thread_variable_get(key) -> obj or nil
136
+ + *
137
+ + * Returns the value of a thread local variable that has been set. Note that
138
+ + * these are different than fiber local values. For fiber local values,
139
+ + * please see Thread#[] and Thread#[]=.
140
+ + *
141
+ + * Thread local values are carried along with threads, and do not respect
142
+ + * fibers. For example:
143
+ + *
144
+ + * Thread.new {
145
+ + * Thread.current.thread_variable_set("foo", "bar") # set a thread local
146
+ + * Thread.current["foo"] = "bar" # set a fiber local
147
+ + *
148
+ + * Fiber.new {
149
+ + * Fiber.yield [
150
+ + * Thread.current.thread_variable_get("foo"), # get the thread local
151
+ + * Thread.current["foo"], # get the fiber local
152
+ + * ]
153
+ + * }.resume
154
+ + * }.join.value # => ['bar', nil]
155
+ + *
156
+ + * The value "bar" is returned for the thread local, where nil is returned
157
+ + * for the fiber local. The fiber is executed in the same thread, so the
158
+ + * thread local values are available.
159
+ + *
160
+ + * See also Thread#[]
161
+ + */
162
+ +
163
+ +static VALUE
164
+ +rb_thread_variable_get(VALUE thread, VALUE id)
165
+ +{
166
+ + VALUE locals;
167
+ + rb_thread_t *th;
168
+ +
169
+ + GetThreadPtr(thread, th);
170
+ +
171
+ + if (rb_safe_level() >= 4 && th != GET_THREAD()) {
172
+ + rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
173
+ + }
174
+ +
175
+ + locals = rb_iv_get(thread, "locals");
176
+ + return rb_hash_aref(locals, ID2SYM(rb_to_id(id)));
177
+ +}
178
+ +
179
+ +/*
180
+ + * call-seq:
181
+ + * thr.thread_variable_set(key, value)
182
+ + *
183
+ + * Sets a thread local with +key+ to +value+. Note that these are local to
184
+ + * threads, and not to fibers. Please see Thread#thread_variable_get and
185
+ + * Thread#[] for more information.
186
+ + */
187
+ +
188
+ +static VALUE
189
+ +rb_thread_variable_set(VALUE thread, VALUE id, VALUE val)
190
+ +{
191
+ + VALUE locals;
192
+ + rb_thread_t *th;
193
+ +
194
+ + GetThreadPtr(thread, th);
195
+ +
196
+ + if (rb_safe_level() >= 4 && th != GET_THREAD()) {
197
+ + rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
198
+ + }
199
+ + if (OBJ_FROZEN(thread)) {
200
+ + rb_error_frozen("thread locals");
201
+ + }
202
+ +
203
+ + locals = rb_iv_get(thread, "locals");
204
+ + return rb_hash_aset(locals, ID2SYM(rb_to_id(id)), val);
205
+ +}
206
+ +
207
+ +/*
208
+ + * call-seq:
209
+ * thr.key?(sym) -> true or false
210
+ *
211
+ * Returns <code>true</code> if the given string (or symbol) exists as a
212
+ @@ -2651,6 +2730,76 @@ rb_thread_keys(VALUE self)
213
+ return ary;
214
+ }
215
+
216
+ +static int
217
+ +keys_i(VALUE key, VALUE value, VALUE ary)
218
+ +{
219
+ + rb_ary_push(ary, key);
220
+ + return ST_CONTINUE;
221
+ +}
222
+ +
223
+ +/*
224
+ + * call-seq:
225
+ + * thr.thread_variables -> array
226
+ + *
227
+ + * Returns an an array of the names of the thread-local variables (as Symbols).
228
+ + *
229
+ + * thr = Thread.new do
230
+ + * Thread.current.thread_variable_set(:cat, 'meow')
231
+ + * Thread.current.thread_variable_set("dog", 'woof')
232
+ + * end
233
+ + * thr.join #=> #<Thread:0x401b3f10 dead>
234
+ + * thr.thread_variables #=> [:dog, :cat]
235
+ + *
236
+ + * Note that these are not fiber local variables. Please see Thread#[] and
237
+ + * Thread#thread_variable_get for more details.
238
+ + */
239
+ +
240
+ +static VALUE
241
+ +rb_thread_variables(VALUE thread)
242
+ +{
243
+ + VALUE locals;
244
+ + VALUE ary;
245
+ +
246
+ + locals = rb_iv_get(thread, "locals");
247
+ + ary = rb_ary_new();
248
+ + rb_hash_foreach(locals, keys_i, ary);
249
+ +
250
+ + return ary;
251
+ +}
252
+ +
253
+ +/*
254
+ + * call-seq:
255
+ + * thr.thread_variable?(key) -> true or false
256
+ + *
257
+ + * Returns <code>true</code> if the given string (or symbol) exists as a
258
+ + * thread-local variable.
259
+ + *
260
+ + * me = Thread.current
261
+ + * me.thread_variable_set(:oliver, "a")
262
+ + * me.thread_variable?(:oliver) #=> true
263
+ + * me.thread_variable?(:stanley) #=> false
264
+ + *
265
+ + * Note that these are not fiber local variables. Please see Thread#[] and
266
+ + * Thread#thread_variable_get for more details.
267
+ + */
268
+ +
269
+ +static VALUE
270
+ +rb_thread_variable_p(VALUE thread, VALUE key)
271
+ +{
272
+ + VALUE locals;
273
+ +
274
+ + locals = rb_iv_get(thread, "locals");
275
+ +
276
+ + if (!RHASH(locals)->ntbl)
277
+ + return Qfalse;
278
+ +
279
+ + if (st_lookup(RHASH(locals)->ntbl, ID2SYM(rb_to_id(key)), 0)) {
280
+ + return Qtrue;
281
+ + }
282
+ +
283
+ + return Qfalse;
284
+ +}
285
+ +
286
+ /*
287
+ * call-seq:
288
+ * thr.priority -> integer
289
+ @@ -4541,6 +4690,10 @@ Init_Thread(void)
290
+ rb_define_method(rb_cThread, "priority", rb_thread_priority, 0);
291
+ rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1);
292
+ rb_define_method(rb_cThread, "status", rb_thread_status, 0);
293
+ + rb_define_method(rb_cThread, "thread_variable_get", rb_thread_variable_get, 1);
294
+ + rb_define_method(rb_cThread, "thread_variable_set", rb_thread_variable_set, 2);
295
+ + rb_define_method(rb_cThread, "thread_variables", rb_thread_variables, 0);
296
+ + rb_define_method(rb_cThread, "thread_variable?", rb_thread_variable_p, 1);
297
+ rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0);
298
+ rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
299
+ rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0);
300
+ diff --git a/vm.c b/vm.c
301
+ index c47b592..5269a50 100644
302
+ --- a/vm.c
303
+ +++ b/vm.c
304
+ @@ -1838,6 +1838,7 @@ ruby_thread_init(VALUE self)
305
+ GetThreadPtr(self, th);
306
+
307
+ th_init(th, self);
308
+ + rb_iv_set(self, "locals", rb_hash_new());
309
+ th->vm = vm;
310
+
311
+ th->top_wrapper = 0;
312
+ @@ -2185,6 +2186,7 @@ Init_VM(void)
313
+
314
+ /* create main thread */
315
+ th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th);
316
+ + rb_iv_set(th_self, "locals", rb_hash_new());
317
+ vm->main_thread = th;
318
+ vm->running_thread = th;
319
+ th->vm = vm;
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thread_variables
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Stefan Kaes
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-11-02 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: Provide thread local variables for ruby 1.9 and API for all ruby versions
22
+ email:
23
+ - stefan.kaes@xing.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - Gemfile
33
+ - LICENSE.txt
34
+ - README.md
35
+ - Rakefile
36
+ - lib/thread_variables.rb
37
+ - lib/thread_variables/version.rb
38
+ - test/colorized_test_output.rb
39
+ - test/thread_variables_test.rb
40
+ - thread_variables.gemspec
41
+ - thread_variables.patch
42
+ homepage: ""
43
+ licenses: []
44
+
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ requirements: []
69
+
70
+ rubyforge_project:
71
+ rubygems_version: 1.8.24
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Provide functionality compatible to latest trunk commit for all ruby version above 1.8
75
+ test_files:
76
+ - test/colorized_test_output.rb
77
+ - test/thread_variables_test.rb