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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/szymanskis_mutex.rb +76 -60
  3. metadata +25 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6538dbfac64f4bdd4bd53fbb5e2807036ed382958326a2df443bf8b37b97aaf8
4
- data.tar.gz: af0cad1545a97ebccfc7534bad9cc527e73901c51d4805772136b79e79c2c59e
3
+ metadata.gz: 63735b01825b9d298bd271d2dc8a6cab38729d52f7b49aae9e8c28d8dacc591a
4
+ data.tar.gz: 3f43c6e9a4106b65558f4afa1b86107a7ca90ba11d470f3484d617d94b0efff8
5
5
  SHA512:
6
- metadata.gz: 4bc341584bb0cdbe2bb73136dba30cace5d3562e0cd1640b60503e0673b157d33611f8684e217c69c59ad3bfa486d07223a004eb80ecdfea403c2723a6fd2054
7
- data.tar.gz: 5b045819425278d099efd33df24fbb5eaf631f98380878ca3b3eb64906528a7a43020c2bfe8d7fffa12b95c1ec4945f2b63707136b164f0c042ec6f5442d5831
6
+ metadata.gz: 34ffa81607a1336bc618a101a5846bd1f31bc0da7e1e22455096333272ae954473b2526ac12d0438476f6f04459c7c0eb0856dacb05672688e75545671ebd56f
7
+ data.tar.gz: 41403cc4967677f84d63769db892181175a19337128f27bf5bb860fc627c88cddfa59d2607394d8c27a411331963fba78066b620b0733c2a82af8a1aa8224b99
@@ -24,77 +24,93 @@
24
24
  # OTHER DEALINGS IN THE SOFTWARE.
25
25
 
26
26
  # Based on the Szymanski's Mutual Exclusion Algorithm
27
- module SzymanskisMutex
28
- # Larger seconds mean less cycles/second but may result in lower completion
29
- SZYMANSKIS_SLEEP = 0.05
30
-
31
- @@flags = {}
32
- @@counter = {}
33
-
34
- def mutual_exclusion(concern)
35
- @@counter[concern] ||= 0
36
- @@flags[concern] ||= {}
37
-
38
- # Suppose @@counter += 1 is an atomic function
39
- my_id = @@counter[concern] += 1
40
-
41
- entry_protocol(concern, my_id)
42
- begin
43
- yield
44
- ensure
45
- exit_protocol(concern, my_id)
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
- # 1: Standing outside waiting room
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
- # Wait for open door
58
- sleep(SZYMANSKIS_SLEEP) while @@flags[concern].values.any? { |f| f > 2 }
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
- # Stand in doorway
61
- @@flags[concern][id] = 3
69
+ # Wait for open door
70
+ sleep(SZYMANSKIS_SLEEP) while @@flags[concern].values.any? { |f| f > 2 }
62
71
 
63
- # Is another process waiting to enter?
64
- if @@flags[concern].values.any? { |f| f == 1 }
72
+ # Stand in doorway
73
+ @@flags[concern][id] = 3
65
74
 
66
- # Wait for other processes to enter
67
- @@flags[concern][id] = 2
75
+ # Is another process waiting to enter?
76
+ if @@flags[concern].values.any? { |f| f == 1 }
68
77
 
69
- # Wait for a process to enter and close the door
70
- sleep(SZYMANSKIS_SLEEP) while @@flags[concern].values.all? { |f| f != 4 }
71
- end
78
+ # Wait for other processes to enter
79
+ @@flags[concern][id] = 2
72
80
 
73
- # Close the entrance door
74
- @@flags[concern][id] = 4
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
- # Wait for lower ids to finish exit protocol
77
- while @@flags[concern].select { |i| i < id }.values.any? { |f| f != 1 }
78
- sleep(SZYMANSKIS_SLEEP)
79
- end
80
- end
85
+ # Close the entrance door
86
+ @@flags[concern][id] = 4
81
87
 
82
- def exit_protocol(concern, id)
83
- # Ensure everyone in the waiting room has realized that the door
84
- # is supposed to be closed
85
- while @@flags[concern].select { |i| i > id }.any? { |f| [2, 3].include?(f) }
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
- # Leave. This will reopen door if nobody is still in the waiting room
90
- @@flags[concern].delete(id)
91
-
92
- return unless @@flags[concern].empty?
93
-
94
- # Prevent counter from increasing indefinitely
95
- @@counter.delete concern
96
- @@flags.delete concern
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.0
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.5'
19
+ version: '3.8'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 3.5.0
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.5'
29
+ version: '3.8'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 3.5.0
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