rwlock 1.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 +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: []
|