rubysl-thread 2.0.3 → 2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a55f798bae750c6f72088c3d3675323adccd2616
4
- data.tar.gz: 322ab9989a8977bc3ae9e46e1ffea6df8feba31c
3
+ metadata.gz: 7040690acee184b06a44732773483676d5a3bb91
4
+ data.tar.gz: 30fd25c832cba84c74908c0dc7775ce7d50607e7
5
5
  SHA512:
6
- metadata.gz: 29ae78fbba23d0d51127317417c976ec2e2bfdad470d25d64b082421b395bbe45d9008840e9e84a77381e92c293a37e932dd4a101ac29599b625e5d75d3765cc
7
- data.tar.gz: 77c41221f5c8a4d8b99e06421e6e36f2b24efadedaf212ba82ef65e54430b5d639dad3685209763617231933d02045c98e91e10e34671a2fcfa36336b5901783
6
+ metadata.gz: fc9e49bf1e8dd3b70b6bb6ed838f2cb942dc0080d3a2bf37441cb39454d4a179636d35773adca12b7de061d66130e69268135d23a10e0ff5a3ccc7aae6371535
7
+ data.tar.gz: 9f162c64d9a1af173f686334d437817fd9590c540752800c46466036d7d2ee8291ba64068acfede4c639f245305c67f7bfcfde651f0ca972702f06e57777e093
@@ -1,5 +1,5 @@
1
1
  module RubySL
2
2
  module Thread
3
- VERSION = "2.0.3"
3
+ VERSION = "2.1"
4
4
  end
5
5
  end
@@ -1 +1,342 @@
1
- require "rubysl/thread"
1
+ #
2
+ # thread.rb - thread support classes
3
+ # $Date: 2006-12-31 07:02:22 -0800 (Sun, 31 Dec 2006) $
4
+ # by Yukihiro Matsumoto <matz@netlab.co.jp>
5
+ #
6
+ # Copyright (C) 2001 Yukihiro Matsumoto
7
+ # Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
8
+ # Copyright (C) 2000 Information-technology Promotion Agency, Japan
9
+ #
10
+
11
+ if $DEBUG
12
+ Thread.abort_on_exception = true
13
+ end
14
+
15
+ #
16
+ # ConditionVariable objects augment class Mutex. Using condition variables,
17
+ # it is possible to suspend while in the middle of a critical section until a
18
+ # resource becomes available.
19
+ #
20
+ # Example:
21
+ #
22
+ # require 'thread'
23
+ #
24
+ # mutex = Mutex.new
25
+ # resource = ConditionVariable.new
26
+ #
27
+ # a = Thread.new {
28
+ # mutex.synchronize {
29
+ # # Thread 'a' now needs the resource
30
+ # resource.wait(mutex)
31
+ # # 'a' can now have the resource
32
+ # }
33
+ # }
34
+ #
35
+ # b = Thread.new {
36
+ # mutex.synchronize {
37
+ # # Thread 'b' has finished using the resource
38
+ # resource.signal
39
+ # }
40
+ # }
41
+ #
42
+ class ConditionVariable
43
+ #
44
+ # Creates a new ConditionVariable
45
+ #
46
+ def initialize
47
+ @waiters = []
48
+ end
49
+
50
+ #
51
+ # Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
52
+ #
53
+ def wait(mutex, timeout=nil)
54
+ Rubinius.lock(self)
55
+
56
+ begin
57
+ wchan = Rubinius::Channel.new
58
+
59
+ begin
60
+ mutex.unlock
61
+ @waiters.push wchan
62
+ Rubinius.unlock(self)
63
+ signaled = wchan.receive_timeout timeout
64
+ ensure
65
+ mutex.lock
66
+ Rubinius.lock(self)
67
+
68
+ unless signaled or @waiters.delete(wchan)
69
+ # we timed out, but got signaled afterwards (e.g. while waiting to
70
+ # acquire @lock), so pass that signal on to the next waiter
71
+ @waiters.shift << true unless @waiters.empty?
72
+ end
73
+ end
74
+
75
+ if timeout
76
+ !!signaled
77
+ else
78
+ self
79
+ end
80
+ ensure
81
+ Rubinius.unlock(self)
82
+ end
83
+ end
84
+
85
+ #
86
+ # Wakes up the first thread in line waiting for this lock.
87
+ #
88
+ def signal
89
+ Rubinius.lock(self)
90
+ begin
91
+ @waiters.shift << true unless @waiters.empty?
92
+ ensure
93
+ Rubinius.unlock(self)
94
+ end
95
+ self
96
+ end
97
+
98
+ #
99
+ # Wakes up all threads waiting for this lock.
100
+ #
101
+ def broadcast
102
+ Rubinius.lock(self)
103
+ begin
104
+ @waiters.shift << true until @waiters.empty?
105
+ ensure
106
+ Rubinius.unlock(self)
107
+ end
108
+ self
109
+ end
110
+ end
111
+
112
+ #
113
+ # This class provides a way to synchronize communication between threads.
114
+ #
115
+ # Example:
116
+ #
117
+ # require 'thread'
118
+ #
119
+ # queue = Queue.new
120
+ #
121
+ # producer = Thread.new do
122
+ # 5.times do |i|
123
+ # sleep rand(i) # simulate expense
124
+ # queue << i
125
+ # puts "#{i} produced"
126
+ # end
127
+ # end
128
+ #
129
+ # consumer = Thread.new do
130
+ # 5.times do |i|
131
+ # value = queue.pop
132
+ # sleep rand(i/2) # simulate expense
133
+ # puts "consumed #{value}"
134
+ # end
135
+ # end
136
+ #
137
+ # consumer.join
138
+ #
139
+ class Queue
140
+ #
141
+ # Creates a new queue.
142
+ #
143
+ def initialize
144
+ @que = []
145
+ @que.taint # enable tainted comunication
146
+ self.taint
147
+ @waiting = []
148
+ @waiting.taint
149
+ @mutex = Mutex.new
150
+ @resource = ConditionVariable.new
151
+ end
152
+
153
+ #
154
+ # Pushes +obj+ to the queue.
155
+ #
156
+ def push(obj)
157
+ @mutex.synchronize do
158
+ @que.push obj
159
+ @resource.signal
160
+ end
161
+ end
162
+
163
+ #
164
+ # Alias of push
165
+ #
166
+ alias << push
167
+
168
+ #
169
+ # Alias of push
170
+ #
171
+ alias enq push
172
+
173
+ #
174
+ # Retrieves data from the queue. If the queue is empty, the calling thread is
175
+ # suspended until data is pushed onto the queue. If +non_block+ is true, the
176
+ # thread isn't suspended, and an exception is raised.
177
+ #
178
+ def pop(non_block=false)
179
+ while true
180
+ @mutex.synchronize do
181
+ #FIXME: some code in net or somewhere violates encapsulation
182
+ #and demands that a waiting queue exist for Queue, as a result
183
+ #we have to do a linear search here to remove the current Thread.
184
+ @waiting.delete(Thread.current)
185
+ if @que.empty?
186
+ raise ThreadError, "queue empty" if non_block
187
+ @waiting.push Thread.current
188
+ @resource.wait(@mutex)
189
+ else
190
+ retval = @que.shift
191
+ @resource.signal
192
+ return retval
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ #
199
+ # Alias of pop
200
+ #
201
+ alias shift pop
202
+
203
+ #
204
+ # Alias of pop
205
+ #
206
+ alias deq pop
207
+
208
+ #
209
+ # Returns +true+ if the queue is empty.
210
+ #
211
+ def empty?
212
+ @que.empty?
213
+ end
214
+
215
+ #
216
+ # Removes all objects from the queue.
217
+ #
218
+ def clear
219
+ @que.clear
220
+ end
221
+
222
+ #
223
+ # Returns the length of the queue.
224
+ #
225
+ def length
226
+ @que.length
227
+ end
228
+
229
+ #
230
+ # Alias of length.
231
+ #
232
+ alias size length
233
+
234
+ #
235
+ # Returns the number of threads waiting on the queue.
236
+ #
237
+ def num_waiting
238
+ @waiting.size
239
+ end
240
+ end
241
+
242
+ #
243
+ # This class represents queues of specified size capacity. The push operation
244
+ # may be blocked if the capacity is full.
245
+ #
246
+ # See Queue for an example of how a SizedQueue works.
247
+ #
248
+ class SizedQueue < Queue
249
+ #
250
+ # Creates a fixed-length queue with a maximum size of +max+.
251
+ #
252
+ def initialize(max)
253
+ raise ArgumentError, "queue size must be positive" unless max > 0
254
+ @max = max
255
+ @queue_wait = []
256
+ @queue_wait.taint # enable tainted comunication
257
+ @size_mutex = Mutex.new
258
+ @sem = ConditionVariable.new
259
+ super()
260
+ end
261
+
262
+ #
263
+ # Returns the maximum size of the queue.
264
+ #
265
+ def max
266
+ @max
267
+ end
268
+
269
+ #
270
+ # Sets the maximum size of the queue.
271
+ #
272
+ def max=(max)
273
+ @size_mutex.synchronize do
274
+ @max = max
275
+ @sem.broadcast
276
+ end
277
+ max
278
+ end
279
+
280
+ #
281
+ # Pushes +obj+ to the queue. If there is no space left in the queue, waits
282
+ # until space becomes available.
283
+ #
284
+ def push(obj)
285
+ while true
286
+ @size_mutex.synchronize do
287
+ @queue_wait.delete(Thread.current)
288
+ if @que.size >= @max
289
+ @queue_wait.push Thread.current
290
+ @sem.wait(@size_mutex)
291
+ else
292
+ return super(obj)
293
+ end
294
+ end
295
+ end
296
+ end
297
+
298
+ #
299
+ # Alias of push
300
+ #
301
+ alias << push
302
+
303
+ #
304
+ # Alias of push
305
+ #
306
+ alias enq push
307
+
308
+ #
309
+ # Retrieves data from the queue and runs a waiting thread, if any.
310
+ #
311
+ def pop(*args)
312
+ retval = super
313
+
314
+ @size_mutex.synchronize do
315
+ if @que.size < @max
316
+ @sem.broadcast
317
+ end
318
+ end
319
+
320
+ return retval
321
+ end
322
+
323
+ #
324
+ # Alias of pop
325
+ #
326
+ alias shift pop
327
+
328
+ #
329
+ # Alias of pop
330
+ #
331
+ alias deq pop
332
+
333
+ #
334
+ # Returns the number of threads waiting on the queue.
335
+ #
336
+ def num_waiting
337
+ @waiting.size + @queue_wait.size
338
+ end
339
+ end
340
+
341
+ # Documentation comments:
342
+ # - How do you make RDoc inherit documentation from superclass?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubysl-thread
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: '2.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Shirai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-21 00:00:00.000000000 Z
11
+ date: 2017-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -81,7 +81,6 @@ files:
81
81
  - README.md
82
82
  - Rakefile
83
83
  - lib/rubysl/thread.rb
84
- - lib/rubysl/thread/thread.rb
85
84
  - lib/rubysl/thread/version.rb
86
85
  - lib/thread.rb
87
86
  - rubysl-thread.gemspec
@@ -106,10 +105,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
105
  version: '0'
107
106
  requirements: []
108
107
  rubyforge_project:
109
- rubygems_version: 2.4.5
108
+ rubygems_version: 2.5.1
110
109
  signing_key:
111
110
  specification_version: 4
112
111
  summary: Support classes for working with threads.
113
112
  test_files:
114
113
  - spec/exclusive_spec.rb
115
- has_rdoc:
@@ -1,342 +0,0 @@
1
- #
2
- # thread.rb - thread support classes
3
- # $Date: 2006-12-31 07:02:22 -0800 (Sun, 31 Dec 2006) $
4
- # by Yukihiro Matsumoto <matz@netlab.co.jp>
5
- #
6
- # Copyright (C) 2001 Yukihiro Matsumoto
7
- # Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
8
- # Copyright (C) 2000 Information-technology Promotion Agency, Japan
9
- #
10
-
11
- if $DEBUG
12
- Thread.abort_on_exception = true
13
- end
14
-
15
- #
16
- # ConditionVariable objects augment class Mutex. Using condition variables,
17
- # it is possible to suspend while in the middle of a critical section until a
18
- # resource becomes available.
19
- #
20
- # Example:
21
- #
22
- # require 'thread'
23
- #
24
- # mutex = Mutex.new
25
- # resource = ConditionVariable.new
26
- #
27
- # a = Thread.new {
28
- # mutex.synchronize {
29
- # # Thread 'a' now needs the resource
30
- # resource.wait(mutex)
31
- # # 'a' can now have the resource
32
- # }
33
- # }
34
- #
35
- # b = Thread.new {
36
- # mutex.synchronize {
37
- # # Thread 'b' has finished using the resource
38
- # resource.signal
39
- # }
40
- # }
41
- #
42
- class ConditionVariable
43
- #
44
- # Creates a new ConditionVariable
45
- #
46
- def initialize
47
- @waiters = []
48
- end
49
-
50
- #
51
- # Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
52
- #
53
- def wait(mutex, timeout=nil)
54
- Rubinius.lock(self)
55
-
56
- begin
57
- wchan = Rubinius::Channel.new
58
-
59
- begin
60
- mutex.unlock
61
- @waiters.push wchan
62
- Rubinius.unlock(self)
63
- signaled = wchan.receive_timeout timeout
64
- ensure
65
- mutex.lock
66
- Rubinius.lock(self)
67
-
68
- unless signaled or @waiters.delete(wchan)
69
- # we timed out, but got signaled afterwards (e.g. while waiting to
70
- # acquire @lock), so pass that signal on to the next waiter
71
- @waiters.shift << true unless @waiters.empty?
72
- end
73
- end
74
-
75
- if timeout
76
- !!signaled
77
- else
78
- self
79
- end
80
- ensure
81
- Rubinius.unlock(self)
82
- end
83
- end
84
-
85
- #
86
- # Wakes up the first thread in line waiting for this lock.
87
- #
88
- def signal
89
- Rubinius.lock(self)
90
- begin
91
- @waiters.shift << true unless @waiters.empty?
92
- ensure
93
- Rubinius.unlock(self)
94
- end
95
- self
96
- end
97
-
98
- #
99
- # Wakes up all threads waiting for this lock.
100
- #
101
- def broadcast
102
- Rubinius.lock(self)
103
- begin
104
- @waiters.shift << true until @waiters.empty?
105
- ensure
106
- Rubinius.unlock(self)
107
- end
108
- self
109
- end
110
- end
111
-
112
- #
113
- # This class provides a way to synchronize communication between threads.
114
- #
115
- # Example:
116
- #
117
- # require 'thread'
118
- #
119
- # queue = Queue.new
120
- #
121
- # producer = Thread.new do
122
- # 5.times do |i|
123
- # sleep rand(i) # simulate expense
124
- # queue << i
125
- # puts "#{i} produced"
126
- # end
127
- # end
128
- #
129
- # consumer = Thread.new do
130
- # 5.times do |i|
131
- # value = queue.pop
132
- # sleep rand(i/2) # simulate expense
133
- # puts "consumed #{value}"
134
- # end
135
- # end
136
- #
137
- # consumer.join
138
- #
139
- class Queue
140
- #
141
- # Creates a new queue.
142
- #
143
- def initialize
144
- @que = []
145
- @que.taint # enable tainted comunication
146
- self.taint
147
- @waiting = []
148
- @waiting.taint
149
- @mutex = Mutex.new
150
- @resource = ConditionVariable.new
151
- end
152
-
153
- #
154
- # Pushes +obj+ to the queue.
155
- #
156
- def push(obj)
157
- @mutex.synchronize do
158
- @que.push obj
159
- @resource.signal
160
- end
161
- end
162
-
163
- #
164
- # Alias of push
165
- #
166
- alias << push
167
-
168
- #
169
- # Alias of push
170
- #
171
- alias enq push
172
-
173
- #
174
- # Retrieves data from the queue. If the queue is empty, the calling thread is
175
- # suspended until data is pushed onto the queue. If +non_block+ is true, the
176
- # thread isn't suspended, and an exception is raised.
177
- #
178
- def pop(non_block=false)
179
- while true
180
- @mutex.synchronize do
181
- #FIXME: some code in net or somewhere violates encapsulation
182
- #and demands that a waiting queue exist for Queue, as a result
183
- #we have to do a linear search here to remove the current Thread.
184
- @waiting.delete(Thread.current)
185
- if @que.empty?
186
- raise ThreadError, "queue empty" if non_block
187
- @waiting.push Thread.current
188
- @resource.wait(@mutex)
189
- else
190
- retval = @que.shift
191
- @resource.signal
192
- return retval
193
- end
194
- end
195
- end
196
- end
197
-
198
- #
199
- # Alias of pop
200
- #
201
- alias shift pop
202
-
203
- #
204
- # Alias of pop
205
- #
206
- alias deq pop
207
-
208
- #
209
- # Returns +true+ if the queue is empty.
210
- #
211
- def empty?
212
- @que.empty?
213
- end
214
-
215
- #
216
- # Removes all objects from the queue.
217
- #
218
- def clear
219
- @que.clear
220
- end
221
-
222
- #
223
- # Returns the length of the queue.
224
- #
225
- def length
226
- @que.length
227
- end
228
-
229
- #
230
- # Alias of length.
231
- #
232
- alias size length
233
-
234
- #
235
- # Returns the number of threads waiting on the queue.
236
- #
237
- def num_waiting
238
- @waiting.size
239
- end
240
- end
241
-
242
- #
243
- # This class represents queues of specified size capacity. The push operation
244
- # may be blocked if the capacity is full.
245
- #
246
- # See Queue for an example of how a SizedQueue works.
247
- #
248
- class SizedQueue < Queue
249
- #
250
- # Creates a fixed-length queue with a maximum size of +max+.
251
- #
252
- def initialize(max)
253
- raise ArgumentError, "queue size must be positive" unless max > 0
254
- @max = max
255
- @queue_wait = []
256
- @queue_wait.taint # enable tainted comunication
257
- @size_mutex = Mutex.new
258
- @sem = ConditionVariable.new
259
- super()
260
- end
261
-
262
- #
263
- # Returns the maximum size of the queue.
264
- #
265
- def max
266
- @max
267
- end
268
-
269
- #
270
- # Sets the maximum size of the queue.
271
- #
272
- def max=(max)
273
- @size_mutex.synchronize do
274
- @max = max
275
- @sem.broadcast
276
- end
277
- max
278
- end
279
-
280
- #
281
- # Pushes +obj+ to the queue. If there is no space left in the queue, waits
282
- # until space becomes available.
283
- #
284
- def push(obj)
285
- while true
286
- @size_mutex.synchronize do
287
- @queue_wait.delete(Thread.current)
288
- if @que.size >= @max
289
- @queue_wait.push Thread.current
290
- @sem.wait(@size_mutex)
291
- else
292
- return super(obj)
293
- end
294
- end
295
- end
296
- end
297
-
298
- #
299
- # Alias of push
300
- #
301
- alias << push
302
-
303
- #
304
- # Alias of push
305
- #
306
- alias enq push
307
-
308
- #
309
- # Retrieves data from the queue and runs a waiting thread, if any.
310
- #
311
- def pop(*args)
312
- retval = super
313
-
314
- @size_mutex.synchronize do
315
- if @que.size < @max
316
- @sem.broadcast
317
- end
318
- end
319
-
320
- return retval
321
- end
322
-
323
- #
324
- # Alias of pop
325
- #
326
- alias shift pop
327
-
328
- #
329
- # Alias of pop
330
- #
331
- alias deq pop
332
-
333
- #
334
- # Returns the number of threads waiting on the queue.
335
- #
336
- def num_waiting
337
- @waiting.size + @queue_wait.size
338
- end
339
- end
340
-
341
- # Documentation comments:
342
- # - How do you make RDoc inherit documentation from superclass?