szymanskis_mutex 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/szymanskis_mutex.rb +76 -60
- metadata +25 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63735b01825b9d298bd271d2dc8a6cab38729d52f7b49aae9e8c28d8dacc591a
|
4
|
+
data.tar.gz: 3f43c6e9a4106b65558f4afa1b86107a7ca90ba11d470f3484d617d94b0efff8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34ffa81607a1336bc618a101a5846bd1f31bc0da7e1e22455096333272ae954473b2526ac12d0438476f6f04459c7c0eb0856dacb05672688e75545671ebd56f
|
7
|
+
data.tar.gz: 41403cc4967677f84d63769db892181175a19337128f27bf5bb860fc627c88cddfa59d2607394d8c27a411331963fba78066b620b0733c2a82af8a1aa8224b99
|
data/lib/szymanskis_mutex.rb
CHANGED
@@ -24,77 +24,93 @@
|
|
24
24
|
# OTHER DEALINGS IN THE SOFTWARE.
|
25
25
|
|
26
26
|
# Based on the Szymanski's Mutual Exclusion Algorithm
|
27
|
-
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
@@counter
|
36
|
-
|
37
|
-
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
27
|
+
class SzymanskisMutex
|
28
|
+
# Metaclass to make code more readable.
|
29
|
+
# The only available method to SzymanskisMutex is #mutual_exclusion
|
30
|
+
class << self
|
31
|
+
# Larger seconds mean less cycles/second but may result in lower completion
|
32
|
+
SZYMANSKIS_SLEEP = 0.05
|
33
|
+
|
34
|
+
@@flags = {}
|
35
|
+
@@counter = {}
|
36
|
+
|
37
|
+
# Provide a MutEx lock
|
38
|
+
# Provide the critical section as a block to this method
|
39
|
+
# Different concerns will prevent unrelated code to wait on each other
|
40
|
+
# Returns the result of the critical code or nil if something fails
|
41
|
+
def mutual_exclusion(concern)
|
42
|
+
@@counter[concern] ||= 0
|
43
|
+
@@flags[concern] ||= {}
|
44
|
+
|
45
|
+
# Suppose @@counter += 1 is an atomic function
|
46
|
+
my_id = @@counter[concern] += 1
|
47
|
+
|
48
|
+
entry_protocol(concern, my_id)
|
49
|
+
begin
|
50
|
+
result = yield
|
51
|
+
ensure
|
52
|
+
# If something fails in the critical section release the resource
|
53
|
+
exit_protocol(concern, my_id)
|
54
|
+
result
|
55
|
+
end
|
46
56
|
end
|
47
|
-
end
|
48
57
|
|
49
|
-
|
50
|
-
# 2: Waiting for other processes to enter
|
51
|
-
# 3: Standing in doorway
|
52
|
-
# 4: Closed entrance door
|
53
|
-
def entry_protocol(concern, id)
|
54
|
-
# Standing outside waiting room
|
55
|
-
@@flags[concern][id] = 1
|
58
|
+
private
|
56
59
|
|
57
|
-
#
|
58
|
-
|
60
|
+
# 1: Standing outside waiting room
|
61
|
+
# 2: Waiting for other processes to enter
|
62
|
+
# 3: Standing in doorway
|
63
|
+
# 4: Closed entrance door
|
64
|
+
# id is the number of the process entering this section relative to concern
|
65
|
+
def entry_protocol(concern, id)
|
66
|
+
# Standing outside waiting room
|
67
|
+
@@flags[concern][id] = 1
|
59
68
|
|
60
|
-
|
61
|
-
|
69
|
+
# Wait for open door
|
70
|
+
sleep(SZYMANSKIS_SLEEP) while @@flags[concern].values.any? { |f| f > 2 }
|
62
71
|
|
63
|
-
|
64
|
-
|
72
|
+
# Stand in doorway
|
73
|
+
@@flags[concern][id] = 3
|
65
74
|
|
66
|
-
#
|
67
|
-
@@flags[concern]
|
75
|
+
# Is another process waiting to enter?
|
76
|
+
if @@flags[concern].values.any? { |f| f == 1 }
|
68
77
|
|
69
|
-
|
70
|
-
|
71
|
-
end
|
78
|
+
# Wait for other processes to enter
|
79
|
+
@@flags[concern][id] = 2
|
72
80
|
|
73
|
-
|
74
|
-
|
81
|
+
# Wait for a process to enter and close the door
|
82
|
+
sleep(SZYMANSKIS_SLEEP) while @@flags[concern].values.all? { |f| f != 4 }
|
83
|
+
end
|
75
84
|
|
76
|
-
|
77
|
-
|
78
|
-
sleep(SZYMANSKIS_SLEEP)
|
79
|
-
end
|
80
|
-
end
|
85
|
+
# Close the entrance door
|
86
|
+
@@flags[concern][id] = 4
|
81
87
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
sleep(SZYMANSKIS_SLEEP)
|
88
|
+
# Wait for lower ids to finish exit protocol
|
89
|
+
while @@flags[concern].select { |i| i < id }.values.any? { |f| f != 1 }
|
90
|
+
sleep(SZYMANSKIS_SLEEP)
|
91
|
+
end
|
87
92
|
end
|
88
93
|
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
94
|
+
# Exit the process and if it is the last one in that batch then
|
95
|
+
# reopens the door for the next batch
|
96
|
+
# id is the number of the process exiting this section relative to concern
|
97
|
+
def exit_protocol(concern, id)
|
98
|
+
# Ensure everyone in the waiting room has realized that the door
|
99
|
+
# is supposed to be closed
|
100
|
+
while @@flags[concern].select { |i| i > id }.any? { |f| [2, 3].include?(f) }
|
101
|
+
sleep(SZYMANSKIS_SLEEP)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Leave. This will reopen door if nobody is still in the waiting room
|
105
|
+
@@flags[concern].delete(id)
|
106
|
+
|
107
|
+
# If there are processes still running this concern there is
|
108
|
+
# nothing else to do
|
109
|
+
return unless @@flags[concern].empty?
|
110
|
+
|
111
|
+
# Prevent counter from increasing indefinitely
|
112
|
+
@@counter.delete concern
|
113
|
+
@@flags.delete concern
|
114
|
+
end
|
97
115
|
end
|
98
|
-
|
99
|
-
protected :entry_protocol, :exit_protocol
|
100
116
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: szymanskis_mutex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emmanuel Byrd
|
@@ -16,20 +16,40 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '3.
|
19
|
+
version: '3.8'
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 3.
|
22
|
+
version: 3.8.0
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '3.
|
29
|
+
version: '3.8'
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 3.
|
32
|
+
version: 3.8.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rspec-core
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3.8'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 3.8.0
|
43
|
+
type: :development
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '3.8'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 3.8.0
|
33
53
|
description: Algorithm devised by Boleslaw Szymanski. This MutEx has linear wait and
|
34
54
|
only 5 communication variables
|
35
55
|
email: emmanuel_pajaro@hotmail.com
|