rubysl-sync 1.0.0 → 2.0.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.
- checksums.yaml +4 -4
- data/.travis.yml +5 -4
- data/lib/rubysl/sync/sync.rb +179 -163
- data/lib/rubysl/sync/version.rb +1 -1
- data/rubysl-sync.gemspec +3 -1
- metadata +18 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66690cb8be8f9de0984431a7b070ec5ad6510406
|
4
|
+
data.tar.gz: bb6306c09d36db252e64c7397af45dd88516fc8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73d2a369784159fc2b5956eed34ffdb216f76b3932cf0bf5feb260e6f1517e38696b05ce5d75a9f992a156d300d02c7594d973a404f499bfc867e8649accd164
|
7
|
+
data.tar.gz: 2528e545551f3738e2eec2eb038409052ef5aa0cccb58fe243cbe5a4fa1d59bec030cd40a9d51c989a67e22dba318e1c349cc78f59f3f7b455e1b04590e37e8e
|
data/.travis.yml
CHANGED
data/lib/rubysl/sync/sync.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
#
|
2
2
|
# sync.rb - 2 phase lock with counter
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
# by Keiju ISHITSUKA(keiju@ishitsuka.com)
|
3
|
+
# $Release Version: 1.0$
|
4
|
+
# $Revision: 40825 $
|
5
|
+
# by Keiju ISHITSUKA(keiju@ishitsuka.com)
|
7
6
|
#
|
8
7
|
# --
|
9
8
|
# Sync_m, Synchronizer_m
|
@@ -11,8 +10,8 @@
|
|
11
10
|
# obj.extend(Sync_m)
|
12
11
|
# or
|
13
12
|
# class Foo
|
14
|
-
#
|
15
|
-
#
|
13
|
+
# include Sync_m
|
14
|
+
# :
|
16
15
|
# end
|
17
16
|
#
|
18
17
|
# Sync_m#sync_mode
|
@@ -23,9 +22,8 @@
|
|
23
22
|
# Sync_m#sync_lock, lock
|
24
23
|
# Sync_m#sync_unlock, unlock
|
25
24
|
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
# Usage:
|
25
|
+
# Sync, Synchronizer:
|
26
|
+
# Usage:
|
29
27
|
# sync = Sync.new
|
30
28
|
#
|
31
29
|
# Sync#mode
|
@@ -36,46 +34,46 @@
|
|
36
34
|
# Sync#lock(mode) -- mode = :EX, :SH, :UN
|
37
35
|
# Sync#unlock
|
38
36
|
# Sync#synchronize(mode) {...}
|
39
|
-
#
|
37
|
+
#
|
40
38
|
#
|
41
39
|
|
42
40
|
unless defined? Thread
|
43
|
-
|
41
|
+
raise "Thread not available for this ruby interpreter"
|
44
42
|
end
|
45
43
|
|
44
|
+
##
|
45
|
+
# A module that provides a two-phase lock with a counter.
|
46
|
+
|
46
47
|
module Sync_m
|
47
|
-
RCS_ID='-$Header$-'
|
48
|
-
|
49
48
|
# lock mode
|
50
49
|
UN = :UN
|
51
50
|
SH = :SH
|
52
51
|
EX = :EX
|
53
|
-
|
52
|
+
|
54
53
|
# exceptions
|
55
54
|
class Err < StandardError
|
56
55
|
def Err.Fail(*opt)
|
57
|
-
Thread.critical = false
|
58
56
|
fail self, sprintf(self::Message, *opt)
|
59
57
|
end
|
60
|
-
|
58
|
+
|
61
59
|
class UnknownLocker < Err
|
62
60
|
Message = "Thread(%s) not locked."
|
63
61
|
def UnknownLocker.Fail(th)
|
64
|
-
|
62
|
+
super(th.inspect)
|
65
63
|
end
|
66
64
|
end
|
67
|
-
|
65
|
+
|
68
66
|
class LockModeFailer < Err
|
69
67
|
Message = "Unknown lock mode(%s)"
|
70
68
|
def LockModeFailer.Fail(mode)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
69
|
+
if mode.id2name
|
70
|
+
mode = id2name
|
71
|
+
end
|
72
|
+
super(mode)
|
75
73
|
end
|
76
74
|
end
|
77
75
|
end
|
78
|
-
|
76
|
+
|
79
77
|
def Sync_m.define_aliases(cl)
|
80
78
|
cl.module_eval %q{
|
81
79
|
alias locked? sync_locked?
|
@@ -87,30 +85,29 @@ module Sync_m
|
|
87
85
|
alias synchronize sync_synchronize
|
88
86
|
}
|
89
87
|
end
|
90
|
-
|
88
|
+
|
91
89
|
def Sync_m.append_features(cl)
|
92
90
|
super
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
91
|
+
# do nothing for Modules
|
92
|
+
# make aliases for Classes.
|
93
|
+
define_aliases(cl) unless cl.instance_of?(Module)
|
94
|
+
self
|
98
95
|
end
|
99
|
-
|
96
|
+
|
100
97
|
def Sync_m.extend_object(obj)
|
101
98
|
super
|
102
|
-
obj.
|
99
|
+
obj.sync_extend
|
103
100
|
end
|
104
101
|
|
105
|
-
def
|
102
|
+
def sync_extend
|
106
103
|
unless (defined? locked? and
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
Sync_m.define_aliases(
|
104
|
+
defined? shared? and
|
105
|
+
defined? exclusive? and
|
106
|
+
defined? lock and
|
107
|
+
defined? unlock and
|
108
|
+
defined? try_lock and
|
109
|
+
defined? synchronize)
|
110
|
+
Sync_m.define_aliases(singleton_class)
|
114
111
|
end
|
115
112
|
sync_initialize
|
116
113
|
end
|
@@ -119,128 +116,140 @@ module Sync_m
|
|
119
116
|
def sync_locked?
|
120
117
|
sync_mode != UN
|
121
118
|
end
|
122
|
-
|
119
|
+
|
123
120
|
def sync_shared?
|
124
121
|
sync_mode == SH
|
125
122
|
end
|
126
|
-
|
123
|
+
|
127
124
|
def sync_exclusive?
|
128
125
|
sync_mode == EX
|
129
126
|
end
|
130
|
-
|
127
|
+
|
131
128
|
# locking methods.
|
132
129
|
def sync_try_lock(mode = EX)
|
133
130
|
return unlock if mode == UN
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
Thread.critical = false
|
138
|
-
ret
|
131
|
+
@sync_mutex.synchronize do
|
132
|
+
sync_try_lock_sub(mode)
|
133
|
+
end
|
139
134
|
end
|
140
|
-
|
135
|
+
|
141
136
|
def sync_lock(m = EX)
|
142
137
|
return unlock if m == UN
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
138
|
+
Thread.handle_interrupt(StandardError => :on_blocking) do
|
139
|
+
while true
|
140
|
+
@sync_mutex.synchronize do
|
141
|
+
begin
|
142
|
+
if sync_try_lock_sub(m)
|
143
|
+
return self
|
144
|
+
else
|
145
|
+
if sync_sh_locker[Thread.current]
|
146
|
+
sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
|
147
|
+
sync_sh_locker.delete(Thread.current)
|
148
|
+
else
|
149
|
+
unless sync_waiting.include?(Thread.current) || sync_upgrade_waiting.reverse_each.any?{|w| w.first == Thread.current }
|
150
|
+
sync_waiting.push Thread.current
|
151
|
+
end
|
152
|
+
end
|
153
|
+
@sync_mutex.sleep
|
154
|
+
end
|
155
|
+
ensure
|
156
|
+
sync_waiting.delete(Thread.current)
|
157
|
+
end
|
158
|
+
end
|
150
159
|
end
|
151
|
-
Thread.stop
|
152
160
|
end
|
153
|
-
Thread.critical = false
|
154
161
|
self
|
155
162
|
end
|
156
|
-
|
163
|
+
|
157
164
|
def sync_unlock(m = EX)
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
end
|
163
|
-
|
164
|
-
m = sync_mode if m == EX and sync_mode == SH
|
165
|
-
|
166
|
-
runnable = false
|
167
|
-
case m
|
168
|
-
when UN
|
169
|
-
Thread.critical = false
|
170
|
-
Err::UnknownLocker.Fail(Thread.current)
|
171
|
-
|
172
|
-
when EX
|
173
|
-
if sync_ex_locker == Thread.current
|
174
|
-
if (self.sync_ex_count = sync_ex_count - 1) == 0
|
175
|
-
self.sync_ex_locker = nil
|
176
|
-
if sync_sh_locker.include?(Thread.current)
|
177
|
-
self.sync_mode = SH
|
178
|
-
else
|
179
|
-
self.sync_mode = UN
|
180
|
-
end
|
181
|
-
runnable = true
|
182
|
-
end
|
183
|
-
else
|
184
|
-
Err::UnknownLocker.Fail(Thread.current)
|
165
|
+
wakeup_threads = []
|
166
|
+
@sync_mutex.synchronize do
|
167
|
+
if sync_mode == UN
|
168
|
+
Err::UnknownLocker.Fail(Thread.current)
|
185
169
|
end
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
170
|
+
|
171
|
+
m = sync_mode if m == EX and sync_mode == SH
|
172
|
+
|
173
|
+
runnable = false
|
174
|
+
case m
|
175
|
+
when UN
|
176
|
+
Err::UnknownLocker.Fail(Thread.current)
|
177
|
+
|
178
|
+
when EX
|
179
|
+
if sync_ex_locker == Thread.current
|
180
|
+
if (self.sync_ex_count = sync_ex_count - 1) == 0
|
181
|
+
self.sync_ex_locker = nil
|
182
|
+
if sync_sh_locker.include?(Thread.current)
|
183
|
+
self.sync_mode = SH
|
184
|
+
else
|
185
|
+
self.sync_mode = UN
|
186
|
+
end
|
187
|
+
runnable = true
|
188
|
+
end
|
189
|
+
else
|
190
|
+
Err::UnknownLocker.Fail(Thread.current)
|
191
|
+
end
|
192
|
+
|
193
|
+
when SH
|
194
|
+
if (count = sync_sh_locker[Thread.current]).nil?
|
195
|
+
Err::UnknownLocker.Fail(Thread.current)
|
196
|
+
else
|
197
|
+
if (sync_sh_locker[Thread.current] = count - 1) == 0
|
198
|
+
sync_sh_locker.delete(Thread.current)
|
199
|
+
if sync_sh_locker.empty? and sync_ex_count == 0
|
200
|
+
self.sync_mode = UN
|
201
|
+
runnable = true
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
198
205
|
end
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
wait = sync_waiting
|
215
|
-
self.sync_waiting = []
|
216
|
-
Thread.critical = false
|
217
|
-
for w in wait
|
218
|
-
w.run
|
219
|
-
end
|
206
|
+
|
207
|
+
if runnable
|
208
|
+
if sync_upgrade_waiting.size > 0
|
209
|
+
th, count = sync_upgrade_waiting.shift
|
210
|
+
sync_sh_locker[th] = count
|
211
|
+
th.wakeup
|
212
|
+
wakeup_threads.push th
|
213
|
+
else
|
214
|
+
wait = sync_waiting
|
215
|
+
self.sync_waiting = []
|
216
|
+
for th in wait
|
217
|
+
th.wakeup
|
218
|
+
wakeup_threads.push th
|
219
|
+
end
|
220
|
+
end
|
220
221
|
end
|
221
222
|
end
|
222
|
-
|
223
|
-
|
223
|
+
for th in wakeup_threads
|
224
|
+
th.run
|
225
|
+
end
|
224
226
|
self
|
225
227
|
end
|
226
|
-
|
228
|
+
|
227
229
|
def sync_synchronize(mode = EX)
|
228
|
-
|
230
|
+
Thread.handle_interrupt(StandardError => :on_blocking) do
|
229
231
|
sync_lock(mode)
|
230
|
-
|
231
|
-
|
232
|
-
|
232
|
+
begin
|
233
|
+
yield
|
234
|
+
ensure
|
235
|
+
sync_unlock
|
236
|
+
end
|
233
237
|
end
|
234
238
|
end
|
235
239
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
240
|
+
attr_accessor :sync_mode
|
241
|
+
|
242
|
+
attr_accessor :sync_waiting
|
243
|
+
attr_accessor :sync_upgrade_waiting
|
244
|
+
attr_accessor :sync_sh_locker
|
245
|
+
attr_accessor :sync_ex_locker
|
246
|
+
attr_accessor :sync_ex_count
|
247
|
+
|
248
|
+
def sync_inspect
|
249
|
+
sync_iv = instance_variables.select{|iv| /^@sync_/ =~ iv.id2name}.collect{|iv| iv.id2name + '=' + instance_eval(iv.id2name).inspect}.join(",")
|
250
|
+
print "<#{self.class}.extend Sync_m: #{inspect}, <Sync_m: #{sync_iv}>"
|
251
|
+
end
|
252
|
+
|
244
253
|
private
|
245
254
|
|
246
255
|
def sync_initialize
|
@@ -250,63 +259,70 @@ module Sync_m
|
|
250
259
|
@sync_sh_locker = Hash.new
|
251
260
|
@sync_ex_locker = nil
|
252
261
|
@sync_ex_count = 0
|
262
|
+
|
263
|
+
@sync_mutex = Mutex.new
|
253
264
|
end
|
254
265
|
|
255
266
|
def initialize(*args)
|
256
|
-
sync_initialize
|
257
267
|
super
|
268
|
+
sync_initialize
|
258
269
|
end
|
259
|
-
|
270
|
+
|
260
271
|
def sync_try_lock_sub(m)
|
261
272
|
case m
|
262
273
|
when SH
|
263
274
|
case sync_mode
|
264
275
|
when UN
|
265
|
-
|
266
|
-
|
267
|
-
|
276
|
+
self.sync_mode = m
|
277
|
+
sync_sh_locker[Thread.current] = 1
|
278
|
+
ret = true
|
268
279
|
when SH
|
269
|
-
|
270
|
-
|
271
|
-
|
280
|
+
count = 0 unless count = sync_sh_locker[Thread.current]
|
281
|
+
sync_sh_locker[Thread.current] = count + 1
|
282
|
+
ret = true
|
272
283
|
when EX
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
284
|
+
# in EX mode, lock will upgrade to EX lock
|
285
|
+
if sync_ex_locker == Thread.current
|
286
|
+
self.sync_ex_count = sync_ex_count + 1
|
287
|
+
ret = true
|
288
|
+
else
|
289
|
+
ret = false
|
290
|
+
end
|
280
291
|
end
|
281
292
|
when EX
|
282
293
|
if sync_mode == UN or
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
294
|
+
sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current)
|
295
|
+
self.sync_mode = m
|
296
|
+
self.sync_ex_locker = Thread.current
|
297
|
+
self.sync_ex_count = 1
|
298
|
+
ret = true
|
288
299
|
elsif sync_mode == EX && sync_ex_locker == Thread.current
|
289
|
-
|
290
|
-
|
300
|
+
self.sync_ex_count = sync_ex_count + 1
|
301
|
+
ret = true
|
291
302
|
else
|
292
|
-
|
303
|
+
ret = false
|
293
304
|
end
|
294
305
|
else
|
295
|
-
Thread.critical = false
|
296
306
|
Err::LockModeFailer.Fail mode
|
297
307
|
end
|
298
308
|
return ret
|
299
309
|
end
|
300
310
|
end
|
311
|
+
|
312
|
+
##
|
313
|
+
# An alias for Sync_m from sync.rb
|
314
|
+
|
301
315
|
Synchronizer_m = Sync_m
|
302
316
|
|
317
|
+
##
|
318
|
+
# A class that provides two-phase lock with a counter. See Sync_m for
|
319
|
+
# details.
|
320
|
+
|
303
321
|
class Sync
|
304
|
-
#Sync_m.extend_class self
|
305
322
|
include Sync_m
|
306
|
-
|
307
|
-
def initialize
|
308
|
-
super
|
309
|
-
end
|
310
|
-
|
311
323
|
end
|
324
|
+
|
325
|
+
##
|
326
|
+
# An alias for Sync from sync.rb. See Sync_m for details.
|
327
|
+
|
312
328
|
Synchronizer = Sync
|
data/lib/rubysl/sync/version.rb
CHANGED
data/rubysl-sync.gemspec
CHANGED
@@ -16,8 +16,10 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
|
+
spec.required_ruby_version = "~> 2.0"
|
20
|
+
|
19
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
20
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
21
23
|
spec.add_development_dependency "mspec", "~> 1.5"
|
22
|
-
spec.add_development_dependency "rubysl-prettyprint", "~>
|
24
|
+
spec.add_development_dependency "rubysl-prettyprint", "~> 2.0"
|
23
25
|
end
|
metadata
CHANGED
@@ -1,71 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubysl-sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Shirai
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '10.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: mspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.5'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.5'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rubysl-prettyprint
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '2.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '2.0'
|
69
69
|
description: Ruby standard library sync.
|
70
70
|
email:
|
71
71
|
- brixen@gmail.com
|
@@ -73,8 +73,8 @@ executables: []
|
|
73
73
|
extensions: []
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
|
-
- .gitignore
|
77
|
-
- .travis.yml
|
76
|
+
- ".gitignore"
|
77
|
+
- ".travis.yml"
|
78
78
|
- Gemfile
|
79
79
|
- LICENSE
|
80
80
|
- README.md
|
@@ -94,19 +94,18 @@ require_paths:
|
|
94
94
|
- lib
|
95
95
|
required_ruby_version: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
|
-
- -
|
97
|
+
- - "~>"
|
98
98
|
- !ruby/object:Gem::Version
|
99
|
-
version: '0'
|
99
|
+
version: '2.0'
|
100
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
|
-
- -
|
102
|
+
- - ">="
|
103
103
|
- !ruby/object:Gem::Version
|
104
104
|
version: '0'
|
105
105
|
requirements: []
|
106
106
|
rubyforge_project:
|
107
|
-
rubygems_version: 2.0
|
107
|
+
rubygems_version: 2.2.0
|
108
108
|
signing_key:
|
109
109
|
specification_version: 4
|
110
110
|
summary: Ruby standard library sync.
|
111
111
|
test_files: []
|
112
|
-
has_rdoc:
|