empathy 0.0.1.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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.rdoc +135 -0
- data/Rakefile +33 -0
- data/TESTING.rdoc +11 -0
- data/empathy.gemspec +23 -0
- data/empathy.mspec +34 -0
- data/lib/empathy.rb +162 -0
- data/lib/empathy/em/condition_variable.rb +57 -0
- data/lib/empathy/em/mutex.rb +70 -0
- data/lib/empathy/em/queue.rb +84 -0
- data/lib/empathy/em/thread.rb +363 -0
- data/lib/empathy/object.rb +19 -0
- data/lib/empathy/thread.rb +8 -0
- data/lib/empathy/version.rb +3 -0
- data/mspec/lib/mspec/empathy.rb +19 -0
- data/mspec/lib/mspec/guards/empathy.rb +10 -0
- data/rubyspec/core/kernel/fixtures/__method__.rb +25 -0
- data/rubyspec/core/kernel/fixtures/autoload_b.rb +5 -0
- data/rubyspec/core/kernel/fixtures/autoload_c.rb +5 -0
- data/rubyspec/core/kernel/fixtures/autoload_d.rb +5 -0
- data/rubyspec/core/kernel/fixtures/caller_fixture1.rb +42 -0
- data/rubyspec/core/kernel/fixtures/caller_fixture2.rb +26 -0
- data/rubyspec/core/kernel/fixtures/chomp.rb +4 -0
- data/rubyspec/core/kernel/fixtures/chomp_f.rb +4 -0
- data/rubyspec/core/kernel/fixtures/chop.rb +4 -0
- data/rubyspec/core/kernel/fixtures/chop_f.rb +4 -0
- data/rubyspec/core/kernel/fixtures/classes.rb +410 -0
- data/rubyspec/core/kernel/fixtures/eval_locals.rb +6 -0
- data/rubyspec/core/kernel/fixtures/eval_return_with_lambda.rb +12 -0
- data/rubyspec/core/kernel/fixtures/eval_return_without_lambda.rb +14 -0
- data/rubyspec/core/kernel/fixtures/test.rb +362 -0
- data/rubyspec/core/kernel/sleep_spec.rb +43 -0
- data/rubyspec/core/mutex/lock_spec.rb +8 -0
- data/rubyspec/core/mutex/locked_spec.rb +8 -0
- data/rubyspec/core/mutex/sleep_spec.rb +56 -0
- data/rubyspec/core/mutex/synchronize_spec.rb +8 -0
- data/rubyspec/core/mutex/try_lock_spec.rb +8 -0
- data/rubyspec/core/mutex/unlock_spec.rb +8 -0
- data/rubyspec/core/thread/abort_on_exception_spec.rb +126 -0
- data/rubyspec/core/thread/add_trace_func_spec.rb +7 -0
- data/rubyspec/core/thread/alive_spec.rb +60 -0
- data/rubyspec/core/thread/allocate_spec.rb +9 -0
- data/rubyspec/core/thread/backtrace_spec.rb +7 -0
- data/rubyspec/core/thread/critical_spec.rb +96 -0
- data/rubyspec/core/thread/current_spec.rb +15 -0
- data/rubyspec/core/thread/element_reference_spec.rb +53 -0
- data/rubyspec/core/thread/element_set_spec.rb +46 -0
- data/rubyspec/core/thread/exclusive_spec.rb +20 -0
- data/rubyspec/core/thread/exit_spec.rb +21 -0
- data/rubyspec/core/thread/fixtures/classes.rb +291 -0
- data/rubyspec/core/thread/fork_spec.rb +9 -0
- data/rubyspec/core/thread/group_spec.rb +5 -0
- data/rubyspec/core/thread/initialize_spec.rb +26 -0
- data/rubyspec/core/thread/inspect_spec.rb +48 -0
- data/rubyspec/core/thread/join_spec.rb +63 -0
- data/rubyspec/core/thread/key_spec.rb +64 -0
- data/rubyspec/core/thread/keys_spec.rb +47 -0
- data/rubyspec/core/thread/kill_spec.rb +21 -0
- data/rubyspec/core/thread/list_spec.rb +38 -0
- data/rubyspec/core/thread/main_spec.rb +10 -0
- data/rubyspec/core/thread/new_spec.rb +56 -0
- data/rubyspec/core/thread/pass_spec.rb +8 -0
- data/rubyspec/core/thread/priority_spec.rb +9 -0
- data/rubyspec/core/thread/raise_spec.rb +225 -0
- data/rubyspec/core/thread/run_spec.rb +9 -0
- data/rubyspec/core/thread/safe_level_spec.rb +6 -0
- data/rubyspec/core/thread/set_trace_func_spec.rb +7 -0
- data/rubyspec/core/thread/shared/exit.rb +173 -0
- data/rubyspec/core/thread/shared/start.rb +51 -0
- data/rubyspec/core/thread/shared/wakeup.rb +59 -0
- data/rubyspec/core/thread/start_spec.rb +9 -0
- data/rubyspec/core/thread/status_spec.rb +48 -0
- data/rubyspec/core/thread/stop_spec.rb +66 -0
- data/rubyspec/core/thread/terminate_spec.rb +11 -0
- data/rubyspec/core/thread/value_spec.rb +36 -0
- data/rubyspec/core/thread/wakeup_spec.rb +7 -0
- data/rubyspec/empathy_spec.rb +26 -0
- data/rubyspec/library/conditionvariable/broadcast_spec.rb +62 -0
- data/rubyspec/library/conditionvariable/signal_spec.rb +64 -0
- data/rubyspec/library/conditionvariable/wait_spec.rb +21 -0
- data/rubyspec/library/mutex/lock_spec.rb +10 -0
- data/rubyspec/library/mutex/locked_spec.rb +10 -0
- data/rubyspec/library/mutex/synchronize_spec.rb +10 -0
- data/rubyspec/library/mutex/try_lock_spec.rb +10 -0
- data/rubyspec/library/mutex/unlock_spec.rb +10 -0
- data/rubyspec/library/queue/append_spec.rb +7 -0
- data/rubyspec/library/queue/clear_spec.rb +15 -0
- data/rubyspec/library/queue/deq_spec.rb +7 -0
- data/rubyspec/library/queue/empty_spec.rb +15 -0
- data/rubyspec/library/queue/enq_spec.rb +7 -0
- data/rubyspec/library/queue/length_spec.rb +7 -0
- data/rubyspec/library/queue/num_waiting_spec.rb +19 -0
- data/rubyspec/library/queue/pop_spec.rb +7 -0
- data/rubyspec/library/queue/push_spec.rb +7 -0
- data/rubyspec/library/queue/shared/deque.rb +37 -0
- data/rubyspec/library/queue/shared/enque.rb +10 -0
- data/rubyspec/library/queue/shared/length.rb +9 -0
- data/rubyspec/library/queue/shift_spec.rb +7 -0
- data/rubyspec/library/queue/size_spec.rb +7 -0
- data/rubyspec/shared/kernel/raise.rb +68 -0
- data/rubyspec/shared/mutex/lock.rb +52 -0
- data/rubyspec/shared/mutex/locked.rb +31 -0
- data/rubyspec/shared/mutex/synchronize.rb +23 -0
- data/rubyspec/shared/mutex/try_lock.rb +30 -0
- data/rubyspec/shared/mutex/unlock.rb +35 -0
- data/rubyspec/spec_helper.rb +48 -0
- data/spec/empathy_spec.rb +129 -0
- data/spec/library_spec.rb +79 -0
- data/spec/spec_helper.rb +6 -0
- metadata +222 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
|
3
|
+
|
|
4
|
+
describe "Thread#[]=" do
|
|
5
|
+
ruby_version_is ""..."1.9" do
|
|
6
|
+
it "raises exceptions on the wrong type of keys" do
|
|
7
|
+
lambda { Thread.current[nil] = true }.should raise_error(TypeError)
|
|
8
|
+
lambda { Thread.current[5] = true }.should raise_error(ArgumentError)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
ruby_version_is "1.9" do
|
|
13
|
+
it "raises exceptions on the wrong type of keys" do
|
|
14
|
+
lambda { Thread.current[nil] = true }.should raise_error(TypeError)
|
|
15
|
+
lambda { Thread.current[5] = true }.should raise_error(TypeError)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "is not shared across fibers" do
|
|
19
|
+
fib = Fiber.new do
|
|
20
|
+
Thread.current[:value] = 1
|
|
21
|
+
Fiber.yield
|
|
22
|
+
Thread.current[:value].should == 1
|
|
23
|
+
end
|
|
24
|
+
fib.resume
|
|
25
|
+
Thread.current[:value].should be_nil
|
|
26
|
+
Thread.current[:value] = 2
|
|
27
|
+
fib.resume
|
|
28
|
+
Thread.current[:value] = 2
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "stores a local in another thread when in a fiber" do
|
|
32
|
+
fib = Fiber.new do
|
|
33
|
+
t = Thread.new do
|
|
34
|
+
sleep
|
|
35
|
+
Thread.current[:value].should == 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
Thread.pass while t.status and t.status != "sleep"
|
|
39
|
+
t[:value] = 1
|
|
40
|
+
t.wakeup
|
|
41
|
+
t.join
|
|
42
|
+
end
|
|
43
|
+
fib.resume
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
ruby_version_is "1.9" do
|
|
4
|
+
describe "Thread.exclusive" do
|
|
5
|
+
before :each do
|
|
6
|
+
ScratchPad.clear
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "yields to the block" do
|
|
10
|
+
Thread.exclusive { ScratchPad.record true }
|
|
11
|
+
ScratchPad.recorded.should == true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "returns the result of yielding" do
|
|
15
|
+
Thread.exclusive { :result }.should == :result
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "needs to be reviewed for spec completeness"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
|
3
|
+
require File.expand_path('../shared/exit', __FILE__)
|
|
4
|
+
|
|
5
|
+
ruby_version_is ""..."1.9.1" do
|
|
6
|
+
describe "Thread#exit" do
|
|
7
|
+
it_behaves_like :thread_exit, :exit
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "Thread#exit!" do
|
|
12
|
+
it "needs to be reviewed for spec completeness"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe "Thread.exit" do
|
|
16
|
+
it "causes the current thread to exit" do
|
|
17
|
+
thread = Thread.new { Thread.exit; sleep }
|
|
18
|
+
thread.join
|
|
19
|
+
thread.status.should be_false
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
unless defined? Channel
|
|
2
|
+
require 'thread'
|
|
3
|
+
class Channel < Queue
|
|
4
|
+
alias receive shift
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module ThreadSpecs
|
|
9
|
+
|
|
10
|
+
class SubThread < Thread
|
|
11
|
+
def initialize(*args)
|
|
12
|
+
super { args.first << 1 }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Status
|
|
17
|
+
attr_reader :thread, :inspect, :status
|
|
18
|
+
def initialize(thread)
|
|
19
|
+
@thread = thread
|
|
20
|
+
@alive = thread.alive?
|
|
21
|
+
@inspect = thread.inspect
|
|
22
|
+
@status = thread.status
|
|
23
|
+
@stop = thread.stop?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def alive?
|
|
27
|
+
@alive
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def stop?
|
|
31
|
+
@stop
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# TODO: In the great Thread spec rewrite, abstract this
|
|
36
|
+
class << self
|
|
37
|
+
attr_accessor :state
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.clear_state
|
|
41
|
+
@state = nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.spin_until_sleeping(t)
|
|
45
|
+
Thread.pass while t.status and t.status != "sleep"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.sleeping_thread
|
|
49
|
+
Thread.new do
|
|
50
|
+
begin
|
|
51
|
+
sleep
|
|
52
|
+
ScratchPad.record :woken
|
|
53
|
+
rescue Object => e
|
|
54
|
+
ScratchPad.record e
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.running_thread
|
|
60
|
+
Thread.new do
|
|
61
|
+
begin
|
|
62
|
+
ThreadSpecs.state = :running
|
|
63
|
+
loop { }
|
|
64
|
+
ScratchPad.record :woken
|
|
65
|
+
rescue Object => e
|
|
66
|
+
ScratchPad.record e
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.completed_thread
|
|
72
|
+
Thread.new {}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.status_of_current_thread
|
|
76
|
+
Thread.new { Status.new(Thread.current) }.value
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def self.status_of_running_thread
|
|
80
|
+
t = running_thread
|
|
81
|
+
Thread.pass while t.status and t.status != "run"
|
|
82
|
+
status = Status.new t
|
|
83
|
+
t.kill
|
|
84
|
+
t.join
|
|
85
|
+
status
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def self.status_of_completed_thread
|
|
89
|
+
t = completed_thread
|
|
90
|
+
t.join
|
|
91
|
+
Status.new t
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def self.status_of_sleeping_thread
|
|
95
|
+
t = sleeping_thread
|
|
96
|
+
Thread.pass while t.status and t.status != 'sleep'
|
|
97
|
+
status = Status.new t
|
|
98
|
+
t.run
|
|
99
|
+
t.join
|
|
100
|
+
status
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def self.status_of_blocked_thread
|
|
104
|
+
m = Mutex.new
|
|
105
|
+
m.lock
|
|
106
|
+
t = Thread.new { m.lock }
|
|
107
|
+
Thread.pass while t.status and t.status != 'sleep'
|
|
108
|
+
status = Status.new t
|
|
109
|
+
m.unlock
|
|
110
|
+
t.join
|
|
111
|
+
status
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def self.status_of_aborting_thread
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def self.status_of_killed_thread
|
|
118
|
+
t = Thread.new { sleep }
|
|
119
|
+
Thread.pass while t.status and t.status != 'sleep'
|
|
120
|
+
t.kill
|
|
121
|
+
t.join
|
|
122
|
+
Status.new t
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def self.status_of_thread_with_uncaught_exception
|
|
126
|
+
t = Thread.new { raise "error" }
|
|
127
|
+
begin
|
|
128
|
+
t.join
|
|
129
|
+
rescue RuntimeError
|
|
130
|
+
end
|
|
131
|
+
Status.new t
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def self.status_of_dying_running_thread
|
|
135
|
+
status = nil
|
|
136
|
+
t = dying_thread_ensures { status = Status.new Thread.current }
|
|
137
|
+
t.join
|
|
138
|
+
status
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def self.status_of_dying_sleeping_thread
|
|
142
|
+
t = dying_thread_ensures { Thread.stop; }
|
|
143
|
+
Thread.pass while t.status and t.status != 'sleep'
|
|
144
|
+
status = Status.new t
|
|
145
|
+
t.wakeup
|
|
146
|
+
t.join
|
|
147
|
+
status
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def self.dying_thread_ensures(kill_method_name=:kill)
|
|
151
|
+
t = Thread.new do
|
|
152
|
+
begin
|
|
153
|
+
Thread.current.send(kill_method_name)
|
|
154
|
+
ensure
|
|
155
|
+
yield
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def self.dying_thread_with_outer_ensure(kill_method_name=:kill)
|
|
161
|
+
t = Thread.new do
|
|
162
|
+
begin
|
|
163
|
+
begin
|
|
164
|
+
Thread.current.send(kill_method_name)
|
|
165
|
+
ensure
|
|
166
|
+
raise "In dying thread"
|
|
167
|
+
end
|
|
168
|
+
ensure
|
|
169
|
+
yield
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def self.join_dying_thread_with_outer_ensure(kill_method_name=:kill)
|
|
175
|
+
t = dying_thread_with_outer_ensure(kill_method_name) { yield }
|
|
176
|
+
lambda { t.join }.should raise_error(RuntimeError, "In dying thread")
|
|
177
|
+
return t
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def self.wakeup_dying_sleeping_thread(kill_method_name=:kill)
|
|
181
|
+
t = ThreadSpecs.dying_thread_ensures(kill_method_name) { yield }
|
|
182
|
+
Thread.pass while t.status and t.status != 'sleep'
|
|
183
|
+
t.wakeup
|
|
184
|
+
t.join
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def self.critical_is_reset
|
|
188
|
+
# Create another thread to verify that it can call Thread.critical=
|
|
189
|
+
t = Thread.new do
|
|
190
|
+
initial_critical = Thread.critical
|
|
191
|
+
Thread.critical = true
|
|
192
|
+
Thread.critical = false
|
|
193
|
+
initial_critical == false && Thread.critical == false
|
|
194
|
+
end
|
|
195
|
+
v = t.value
|
|
196
|
+
t.join
|
|
197
|
+
v
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def self.counter
|
|
201
|
+
@@counter
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def self.counter= c
|
|
205
|
+
@@counter = c
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def self.increment_counter(incr)
|
|
209
|
+
incr.times do
|
|
210
|
+
begin
|
|
211
|
+
Thread.critical = true
|
|
212
|
+
@@counter += 1
|
|
213
|
+
ensure
|
|
214
|
+
Thread.critical = false
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def self.critical_thread1()
|
|
220
|
+
Thread.critical = true
|
|
221
|
+
Thread.current.key?(:thread_specs).should == false
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def self.critical_thread2(isThreadStop)
|
|
225
|
+
Thread.current[:thread_specs].should == 101
|
|
226
|
+
Thread.critical.should == !isThreadStop
|
|
227
|
+
if not isThreadStop
|
|
228
|
+
Thread.critical = false
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def self.main_thread1(critical_thread, isThreadSleep, isThreadStop)
|
|
233
|
+
# Thread.stop resets Thread.critical. Also, with native threads, the Thread.Stop may not have executed yet
|
|
234
|
+
# since the main thread will race with the critical thread
|
|
235
|
+
if not isThreadStop
|
|
236
|
+
Thread.critical.should == true
|
|
237
|
+
end
|
|
238
|
+
critical_thread[:thread_specs] = 101
|
|
239
|
+
if isThreadSleep or isThreadStop
|
|
240
|
+
# Thread#wakeup calls are not queued up. So we need to ensure that the thread is sleeping before calling wakeup
|
|
241
|
+
Thread.pass while critical_thread.status and critical_thread.status != "sleep"
|
|
242
|
+
critical_thread.wakeup
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def self.main_thread2(critical_thread)
|
|
247
|
+
Thread.pass # The join below seems to cause a deadlock with CRuby unless Thread.pass is called first
|
|
248
|
+
critical_thread.join
|
|
249
|
+
Thread.critical.should == false
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def self.critical_thread_yields_to_main_thread(isThreadSleep=false, isThreadStop=false)
|
|
253
|
+
@@after_first_sleep = false
|
|
254
|
+
|
|
255
|
+
critical_thread = Thread.new do
|
|
256
|
+
Thread.pass while Thread.main.status and Thread.main.status != "sleep"
|
|
257
|
+
critical_thread1()
|
|
258
|
+
Thread.main.wakeup
|
|
259
|
+
yield
|
|
260
|
+
Thread.pass while @@after_first_sleep != true # Need to ensure that the next statement does not see the first sleep itself
|
|
261
|
+
Thread.pass while Thread.main.status and Thread.main.status != "sleep"
|
|
262
|
+
critical_thread2(isThreadStop)
|
|
263
|
+
Thread.main.wakeup
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
sleep 5
|
|
267
|
+
@@after_first_sleep = true
|
|
268
|
+
main_thread1(critical_thread, isThreadSleep, isThreadStop)
|
|
269
|
+
sleep 5
|
|
270
|
+
main_thread2(critical_thread)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def self.create_critical_thread()
|
|
274
|
+
critical_thread = Thread.new do
|
|
275
|
+
Thread.critical = true
|
|
276
|
+
yield
|
|
277
|
+
Thread.critical = false
|
|
278
|
+
end
|
|
279
|
+
return critical_thread
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def self.create_and_kill_critical_thread(passAfterKill=false)
|
|
283
|
+
critical_thread = ThreadSpecs.create_critical_thread do
|
|
284
|
+
Thread.current.kill
|
|
285
|
+
if passAfterKill
|
|
286
|
+
Thread.pass
|
|
287
|
+
end
|
|
288
|
+
ScratchPad.record("status=" + Thread.current.status)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
|
3
|
+
require File.expand_path('../shared/start', __FILE__)
|
|
4
|
+
|
|
5
|
+
describe "Thread.fork" do
|
|
6
|
+
describe "Thread.start" do
|
|
7
|
+
it_behaves_like :thread_start, :fork
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
|
3
|
+
|
|
4
|
+
describe "Thread#initialize" do
|
|
5
|
+
|
|
6
|
+
describe "already initialized" do
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
@t = Thread.new { sleep }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
after do
|
|
13
|
+
@t.kill
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "raises a ThreadError" do
|
|
17
|
+
lambda {
|
|
18
|
+
@t.instance_eval do
|
|
19
|
+
initialize {}
|
|
20
|
+
end
|
|
21
|
+
}.should raise_error(ThreadError)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
|
3
|
+
|
|
4
|
+
describe "Thread#inspect" do
|
|
5
|
+
it "can check it's own status" do
|
|
6
|
+
ThreadSpecs.status_of_current_thread.inspect.should include('run')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "describes a running thread" do
|
|
10
|
+
ThreadSpecs.status_of_running_thread.inspect.should include('run')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "describes a sleeping thread" do
|
|
14
|
+
ThreadSpecs.status_of_sleeping_thread.inspect.should include('sleep')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "describes a blocked thread" do
|
|
18
|
+
ThreadSpecs.status_of_blocked_thread.inspect.should include('sleep')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "describes a completed thread" do
|
|
22
|
+
ThreadSpecs.status_of_completed_thread.inspect.should include('dead')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "describes a killed thread" do
|
|
26
|
+
ThreadSpecs.status_of_killed_thread.inspect.should include('dead')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "describes a thread with an uncaught exception" do
|
|
30
|
+
ThreadSpecs.status_of_thread_with_uncaught_exception.inspect.should include('dead')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
ruby_version_is ""..."1.9" do
|
|
34
|
+
it "describes a dying running thread" do
|
|
35
|
+
ThreadSpecs.status_of_dying_running_thread.inspect.should include('aborting')
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "describes a dying sleeping thread" do
|
|
40
|
+
ThreadSpecs.status_of_dying_sleeping_thread.status.should include('sleep')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
quarantine! do
|
|
44
|
+
it "reports aborting on a killed thread" do
|
|
45
|
+
ThreadSpecs.status_of_aborting_thread.inspect.should include('aborting')
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|