rwlock 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/lib/rwlock.rb +87 -0
- data/lib/rwlock/sized_queue_patch.rb +29 -0
- metadata +46 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YTJjZTUxZTcyYmQyZDEwY2Q3ZDY2MmNjODllMjMyNTM1OTkxYzZhYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OTVlYTlmM2VhOGY0YmU3YTY5ODVjZTlkMjhlY2RhNDE2ZjQ2YTE5Yg==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NTIwODgzMWRiNzgxMWM2MDViZjc2MWMxODhhYjNkNTU2YjA4YWY1MGI0MmY3
|
10
|
+
NDFkMWEwY2I4NWQ4MmRiNjBlZWNlYTAyN2QwNTE3YWY1YzM5ZmE4ZmQ2YmU5
|
11
|
+
ZmZmMmEzNjM5MjI0ZTAzZjM5YjUzMzRjNGJmN2ViM2YwOGFhMjc=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
M2I4ZjdkZmVmMjhmNGYxZjEzOTk0NTBlZTBhMzVjNDc1MjhmODJhZWE1ODhm
|
14
|
+
MWFkZGM2OGRlNzY3MTAxYjNhOWM4ODZlODcwN2Y3MTNmNmE5M2E5OTFjN2Zh
|
15
|
+
ZmUxMGY4YTBjYzc0OWI2ODU2MjdkOWRiMjc0YmMyZjM4MzI0NDY=
|
data/lib/rwlock.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'thread'
|
2
|
+
if defined? require_relative
|
3
|
+
require_relative 'rwlock/sized_queue_patch'
|
4
|
+
else
|
5
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "rwlock", "sized_queue_patch")
|
6
|
+
end
|
7
|
+
|
8
|
+
# This class provides a simple readers-writer lock (RWLock).
|
9
|
+
# A RWLock allows multiple "readers" to access a resource simultaneously
|
10
|
+
# but "writers" must have exclusive access. In other words, during a "write"
|
11
|
+
# only a single thread may have access to the resource.
|
12
|
+
#
|
13
|
+
# This RWLock prevents writer starvation. While there are no hard guarantees,
|
14
|
+
# if a writer requests access it will generally get access as soon as all
|
15
|
+
# current readers are finished.
|
16
|
+
#
|
17
|
+
# When the current writer is finished, waiting readers have first opportunity
|
18
|
+
# to grab the lock. This should result in no starvation of either readers nor
|
19
|
+
# writers, although access may not be "fair".
|
20
|
+
class RWLock
|
21
|
+
# Creates new readers-writers lock.
|
22
|
+
# The `max_size` argument limits how many readers may read simultaneously.
|
23
|
+
# A limit is necessary to prevent writer starvation.
|
24
|
+
def initialize max_size = 10
|
25
|
+
@write_lock = Mutex.new
|
26
|
+
@q = SizedQueue.new(max_size)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Obtains reading lock and executes block, then releases reading lock.
|
30
|
+
# Many calls to RWLock#read_sync may execute in parallel, but wil not
|
31
|
+
# overlap with calls to RWLock#write_sync.
|
32
|
+
#
|
33
|
+
# If the number of readers is currently at the maximum or a write operation
|
34
|
+
# is in progress, this method will wait. When a reading spot is available and
|
35
|
+
# no write operations are occurring, then the block will be executed.
|
36
|
+
#
|
37
|
+
# rwl = RWLock.new
|
38
|
+
# a = [1, 2, 3]
|
39
|
+
#
|
40
|
+
# Thread.new do
|
41
|
+
# rwl.read_sync do
|
42
|
+
# puts a[1]
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
def read_sync
|
46
|
+
@q.push true
|
47
|
+
yield
|
48
|
+
ensure
|
49
|
+
@q.pop
|
50
|
+
end
|
51
|
+
|
52
|
+
# Obtains writing lock and executes block, then releases writing lock.
|
53
|
+
# The block will have exclusive access to the lock, with no readers or
|
54
|
+
# other writers allowed to execute at the same time.
|
55
|
+
#
|
56
|
+
# If any readers are executing, the method will wait until the current
|
57
|
+
# readers are finished then the block will be executed.
|
58
|
+
#
|
59
|
+
# If another writer is executing, the method will wait until the current
|
60
|
+
# writer is finished. However, readers have first chance at access after a
|
61
|
+
# write.
|
62
|
+
#
|
63
|
+
# rwl = RWLock.new
|
64
|
+
# a = [1, 2, 3]
|
65
|
+
#
|
66
|
+
# Thread.new do
|
67
|
+
# rwl.write_sync do
|
68
|
+
# a[1] += 1
|
69
|
+
# end
|
70
|
+
# end
|
71
|
+
def write_sync
|
72
|
+
@write_lock.synchronize do
|
73
|
+
@q.max.times { @q.push true }
|
74
|
+
|
75
|
+
begin
|
76
|
+
yield
|
77
|
+
ensure
|
78
|
+
@q.clear
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the set maximum number of simultaneous readers.
|
84
|
+
def max
|
85
|
+
@q.max
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
if not SizedQueue.instance_methods(false).include? :clear
|
2
|
+
if RUBY_VERSION == "1.9.3" and RUBY_PATCHLEVEL < 545
|
3
|
+
class SizedQueue
|
4
|
+
# Removes all objects from the queue and wakes waiting threads, if any.
|
5
|
+
def clear
|
6
|
+
@mutex.synchronize do
|
7
|
+
@que.clear
|
8
|
+
begin
|
9
|
+
until @queue_wait.empty?
|
10
|
+
@queue_wait.shift.wakeup
|
11
|
+
end
|
12
|
+
rescue ThreadError
|
13
|
+
retry
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
elsif RUBY_VERSION == "2.0.0"
|
19
|
+
class SizedQueue
|
20
|
+
# Removes all objects from the queue and wakes waiting threads, if any.
|
21
|
+
def clear
|
22
|
+
@mutex.synchronize do
|
23
|
+
@que.clear
|
24
|
+
@enque_cond.signal
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rwlock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Collins
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-27 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Simple thread-level readers-writer lock in pure Ruby. Allows multiple
|
14
|
+
readers to access a resource while writers get exclusive access.
|
15
|
+
email:
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/rwlock.rb
|
21
|
+
- lib/rwlock/sized_queue_patch.rb
|
22
|
+
homepage: https://github.com/presidentbeef/rwlock
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
metadata: {}
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 2.2.2
|
43
|
+
signing_key:
|
44
|
+
specification_version: 4
|
45
|
+
summary: Simple readers-writer lock.
|
46
|
+
test_files: []
|