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.
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