thread_variables 0.1.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,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