szymanskis_mutex 0.1.0 → 0.1.1
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 +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
|