tsafe 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|