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.
@@ -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=
@@ -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: []