rubysl-thread 2.0.3 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
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?