tsafe 0.0.4 → 0.0.5
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.
- data/VERSION +1 -1
- data/lib/tsafe.rb +1 -1
- data/{include/monarray.rb → lib/tsafe_monarray.rb} +0 -0
- data/{include/monhash.rb → lib/tsafe_monhash.rb} +0 -0
- data/{include/monitored.rb → lib/tsafe_monitored.rb} +0 -0
- data/{include/mrswlock.rb → lib/tsafe_mrswlock.rb} +29 -7
- data/{include/mutexed.rb → lib/tsafe_mutexed.rb} +0 -0
- data/{include/proxy.rb → lib/tsafe_proxy.rb} +0 -0
- data/spec/mrswlock_spec.rb +55 -6
- data/tsafe.gemspec +7 -7
- metadata +8 -8
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.5
|
data/lib/tsafe.rb
CHANGED
@@ -4,7 +4,7 @@ require "monitor"
|
|
4
4
|
module Tsafe
|
5
5
|
#Autoloader for subclasses.
|
6
6
|
def self.const_missing(name)
|
7
|
-
require "#{File.dirname(__FILE__)}
|
7
|
+
require "#{File.dirname(__FILE__)}/tsafe_#{name.to_s.downcase}.rb"
|
8
8
|
raise "Still not loaded: '#{name}'." if !Tsafe.const_defined?(name)
|
9
9
|
return Tsafe.const_get(name)
|
10
10
|
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -6,20 +6,30 @@ class Tsafe::Mrswlock
|
|
6
6
|
def initialize
|
7
7
|
@reads = 0
|
8
8
|
@w_mutex = Mutex.new
|
9
|
+
|
10
|
+
#This variable is used to allow reads from the writing thread (monitor-behavior).
|
11
|
+
@locked_by = nil
|
12
|
+
|
13
|
+
#This hash holds thread-IDs for threads that are reading.
|
14
|
+
@reading_threads = {}
|
9
15
|
end
|
10
16
|
|
11
17
|
# Runs the given block through the read-synchronization.
|
12
18
|
def rsync
|
13
19
|
begin
|
14
|
-
|
20
|
+
tid = Thread.current.__id__
|
21
|
+
|
22
|
+
while @w_mutex.locked? and @locked_by != tid
|
15
23
|
Thread.pass
|
16
24
|
print "Passed because lock.\n" if @@debug
|
17
25
|
end
|
18
26
|
|
27
|
+
@reading_threads[tid] = true
|
19
28
|
@reads += 1
|
20
29
|
print "Reading more than one at a time! (#{@reads})\n" if @@debug and @reads >= 2
|
21
30
|
yield
|
22
31
|
ensure
|
32
|
+
@reading_threads.delete(tid)
|
23
33
|
@reads -= 1
|
24
34
|
end
|
25
35
|
end
|
@@ -31,13 +41,25 @@ class Tsafe::Mrswlock
|
|
31
41
|
# end
|
32
42
|
def wsync
|
33
43
|
@w_mutex.synchronize do
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
44
|
+
begin
|
45
|
+
tid = Thread.current.__id__
|
46
|
+
@locked_by = tid
|
47
|
+
|
48
|
+
#Wait for any reads to finish that might have started while we were getting the lock.
|
49
|
+
#Also allow write if there is only one reading thread and that reading thread is the current thread.
|
50
|
+
while @reads > 0
|
51
|
+
if @reading_threads.key?(tid)
|
52
|
+
raise ThreadError, "Deadlock: Writing is not allowed while reading."
|
53
|
+
end
|
54
|
+
|
55
|
+
Thread.pass
|
56
|
+
print "Passed because reading.\n" if @@debug
|
57
|
+
end
|
58
|
+
|
59
|
+
yield
|
60
|
+
ensure
|
61
|
+
@locked_by = nil
|
38
62
|
end
|
39
|
-
|
40
|
-
yield
|
41
63
|
end
|
42
64
|
end
|
43
65
|
|
File without changes
|
File without changes
|
data/spec/mrswlock_spec.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
|
+
require "timeout"
|
4
|
+
|
3
5
|
describe "Tsafe::Rwmutex" do
|
4
|
-
it "should work
|
6
|
+
it "should work with the modified hash" do
|
5
7
|
Thread.abort_on_exception = true
|
6
8
|
debug = false
|
7
9
|
|
@@ -22,10 +24,10 @@ describe "Tsafe::Rwmutex" do
|
|
22
24
|
|
23
25
|
ts = []
|
24
26
|
|
25
|
-
1.upto(
|
27
|
+
1.upto(10) do |tcount|
|
26
28
|
print "Starting thread #{tcount}\n" if debug
|
27
29
|
ts << Thread.new do
|
28
|
-
1.upto(
|
30
|
+
1.upto(5000) do |count|
|
29
31
|
hash[count] = count
|
30
32
|
|
31
33
|
hash[count]
|
@@ -46,7 +48,7 @@ describe "Tsafe::Rwmutex" do
|
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
|
-
it "should work
|
51
|
+
it "should work with manual lock creation" do
|
50
52
|
debug = false
|
51
53
|
|
52
54
|
hash = {}
|
@@ -58,9 +60,9 @@ describe "Tsafe::Rwmutex" do
|
|
58
60
|
rwm = Tsafe::Mrswlock.new
|
59
61
|
ts = []
|
60
62
|
|
61
|
-
1.upto(
|
63
|
+
1.upto(10) do
|
62
64
|
ts << Thread.new do
|
63
|
-
1.upto(
|
65
|
+
1.upto(5000) do |count|
|
64
66
|
rwm.wsync do
|
65
67
|
hash[count] = count
|
66
68
|
end
|
@@ -88,4 +90,51 @@ describe "Tsafe::Rwmutex" do
|
|
88
90
|
t.join
|
89
91
|
end
|
90
92
|
end
|
93
|
+
|
94
|
+
it "should be able to read while writing from same thread while other threads are stressing" do
|
95
|
+
hash = Tsafe::MonHash.new
|
96
|
+
0.upto(1000) do |count|
|
97
|
+
hash[count] = count
|
98
|
+
end
|
99
|
+
|
100
|
+
Timeout.timeout(7) do
|
101
|
+
ts = []
|
102
|
+
1.upto(5) do
|
103
|
+
ts << Thread.new do
|
104
|
+
hash.keep_if do |key, val|
|
105
|
+
hash.each do |key2, val2|
|
106
|
+
#ignore.
|
107
|
+
end
|
108
|
+
|
109
|
+
if key > 500
|
110
|
+
true
|
111
|
+
else
|
112
|
+
false
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
ts.each do |t|
|
119
|
+
t.join
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should not be able to write while reading from same thread" do
|
125
|
+
hash = Tsafe::MonHash.new
|
126
|
+
0.upto(1000) do |count|
|
127
|
+
hash[count] = count
|
128
|
+
end
|
129
|
+
|
130
|
+
begin
|
131
|
+
hash.each do |key, val|
|
132
|
+
hash.delete(key)
|
133
|
+
end
|
134
|
+
|
135
|
+
raise "Expected ThreadError but didnt get raised."
|
136
|
+
rescue ThreadError
|
137
|
+
#ignore - supposed to happen.
|
138
|
+
end
|
139
|
+
end
|
91
140
|
end
|
data/tsafe.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{tsafe}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.5"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kasper Johansen"]
|
@@ -25,13 +25,13 @@ Gem::Specification.new do |s|
|
|
25
25
|
"README.rdoc",
|
26
26
|
"Rakefile",
|
27
27
|
"VERSION",
|
28
|
-
"include/monarray.rb",
|
29
|
-
"include/monhash.rb",
|
30
|
-
"include/monitored.rb",
|
31
|
-
"include/mrswlock.rb",
|
32
|
-
"include/mutexed.rb",
|
33
|
-
"include/proxy.rb",
|
34
28
|
"lib/tsafe.rb",
|
29
|
+
"lib/tsafe_monarray.rb",
|
30
|
+
"lib/tsafe_monhash.rb",
|
31
|
+
"lib/tsafe_monitored.rb",
|
32
|
+
"lib/tsafe_mrswlock.rb",
|
33
|
+
"lib/tsafe_mutexed.rb",
|
34
|
+
"lib/tsafe_proxy.rb",
|
35
35
|
"spec/mrswlock_spec.rb",
|
36
36
|
"spec/spec_helper.rb",
|
37
37
|
"spec/tsafe_spec.rb",
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: tsafe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.5
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Kasper Johansen
|
@@ -75,13 +75,13 @@ files:
|
|
75
75
|
- README.rdoc
|
76
76
|
- Rakefile
|
77
77
|
- VERSION
|
78
|
-
- include/monarray.rb
|
79
|
-
- include/monhash.rb
|
80
|
-
- include/monitored.rb
|
81
|
-
- include/mrswlock.rb
|
82
|
-
- include/mutexed.rb
|
83
|
-
- include/proxy.rb
|
84
78
|
- lib/tsafe.rb
|
79
|
+
- lib/tsafe_monarray.rb
|
80
|
+
- lib/tsafe_monhash.rb
|
81
|
+
- lib/tsafe_monitored.rb
|
82
|
+
- lib/tsafe_mrswlock.rb
|
83
|
+
- lib/tsafe_mutexed.rb
|
84
|
+
- lib/tsafe_proxy.rb
|
85
85
|
- spec/mrswlock_spec.rb
|
86
86
|
- spec/spec_helper.rb
|
87
87
|
- spec/tsafe_spec.rb
|
@@ -100,7 +100,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
hash:
|
103
|
+
hash: -2179111406446538403
|
104
104
|
segments:
|
105
105
|
- 0
|
106
106
|
version: "0"
|