atomic-ruby 0.6.6 → 0.7.0
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/CHANGELOG.md +4 -0
- data/lib/atomic-ruby/atomic_boolean.rb +4 -6
- data/lib/atomic-ruby/atomic_count_down_latch.rb +15 -8
- data/lib/atomic-ruby/atomic_thread_pool.rb +54 -31
- data/lib/atomic-ruby/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 673339dcf17f8da8f0f34326cb31a5a1514b820b4c31229f0022290f50c0a7fe
|
|
4
|
+
data.tar.gz: 289ebbf398e1f2a9bc2b58623680525c02b57056789a589c329f51977b46c250
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5d495876e6706f589bbe91dcea4ad2ba71ab525b32ad897cdd6762de2a3451de91874c7446d8a439323e316d6b13f9748f19f304871a435916deb40e2f9239f6
|
|
7
|
+
data.tar.gz: be35ad1d840b4ea84eecf942087571a7f78b44bb04b3365f18491fed64fc2b5d3fb2182a614a05ad66b55e723c39680d7aa19810aa57bcd24a0166971bd1761c
|
data/CHANGELOG.md
CHANGED
|
@@ -4,14 +4,12 @@ require_relative "atom"
|
|
|
4
4
|
|
|
5
5
|
module AtomicRuby
|
|
6
6
|
class AtomicBoolean
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
|
11
|
-
raise InvalidBooleanError, "expected boolean to be a `TrueClass` or `FalseClass`, got #{value.class}"
|
|
7
|
+
def initialize(boolean)
|
|
8
|
+
unless boolean.is_a?(TrueClass) || boolean.is_a?(FalseClass)
|
|
9
|
+
raise ArgumentError, "boolean must be a TrueClass or FalseClass, got #{boolean.class}"
|
|
12
10
|
end
|
|
13
11
|
|
|
14
|
-
@boolean = Atom.new(
|
|
12
|
+
@boolean = Atom.new(boolean)
|
|
15
13
|
|
|
16
14
|
Ractor.make_shareable(self)
|
|
17
15
|
end
|
|
@@ -4,12 +4,12 @@ require_relative "atom"
|
|
|
4
4
|
|
|
5
5
|
module AtomicRuby
|
|
6
6
|
class AtomicCountDownLatch
|
|
7
|
-
class
|
|
8
|
-
class AlreadyCountedDownError <
|
|
7
|
+
class Error < StandardError; end
|
|
8
|
+
class AlreadyCountedDownError < Error; end
|
|
9
9
|
|
|
10
10
|
def initialize(count)
|
|
11
|
-
unless count.is_a?(Integer)
|
|
12
|
-
raise
|
|
11
|
+
unless count.is_a?(Integer) && count > 0
|
|
12
|
+
raise ArgumentError, "count must be a positive Integer, got #{count.class}"
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
@count = Atom.new(count)
|
|
@@ -22,11 +22,18 @@ module AtomicRuby
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def count_down
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
already_counted_down = false
|
|
26
|
+
new_count = @count.swap do |current_count|
|
|
27
|
+
if current_count == 0
|
|
28
|
+
already_counted_down = true
|
|
29
|
+
current_count
|
|
30
|
+
else
|
|
31
|
+
current_count - 1
|
|
32
|
+
end
|
|
27
33
|
end
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
raise AlreadyCountedDownError, "already counted down to zero" if already_counted_down
|
|
35
|
+
|
|
36
|
+
new_count
|
|
30
37
|
end
|
|
31
38
|
|
|
32
39
|
def wait
|
|
@@ -1,35 +1,38 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "atom"
|
|
4
|
-
require_relative "atomic_boolean"
|
|
5
4
|
|
|
6
5
|
module AtomicRuby
|
|
7
6
|
class AtomicThreadPool
|
|
8
|
-
class
|
|
9
|
-
|
|
7
|
+
class Error < StandardError; end
|
|
8
|
+
|
|
9
|
+
class EnqueuedWorkAfterShutdownError < Error
|
|
10
|
+
def message = "cannot queue work after shutdown"
|
|
11
|
+
end
|
|
10
12
|
|
|
11
13
|
def initialize(size:, name: nil)
|
|
14
|
+
raise ArgumentError, "size must be a positive Integer" unless size.is_a?(Integer) && size > 0
|
|
15
|
+
raise ArgumentError, "name must be a String" unless name.nil? || name.is_a?(String)
|
|
16
|
+
|
|
12
17
|
@size = size
|
|
13
18
|
@name = name
|
|
14
|
-
|
|
15
|
-
@
|
|
19
|
+
|
|
20
|
+
@state = Atom.new(queue: [], shutdown: false)
|
|
16
21
|
@started_threads = Atom.new(0)
|
|
17
|
-
@
|
|
22
|
+
@threads = []
|
|
18
23
|
|
|
19
24
|
start
|
|
20
25
|
end
|
|
21
26
|
|
|
22
27
|
def <<(work)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
state = @state.swap do |current_state|
|
|
29
|
+
if current_state[:shutdown]
|
|
30
|
+
current_state
|
|
31
|
+
else
|
|
32
|
+
current_state.merge(queue: [*current_state[:queue], work])
|
|
33
|
+
end
|
|
29
34
|
end
|
|
30
|
-
|
|
31
|
-
@queue.swap { |current_queue| current_queue += [work] }
|
|
32
|
-
true
|
|
35
|
+
raise EnqueuedWorkAfterShutdownError if state[:shutdown]
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
def length
|
|
@@ -37,20 +40,31 @@ module AtomicRuby
|
|
|
37
40
|
end
|
|
38
41
|
|
|
39
42
|
def queue_length
|
|
40
|
-
@
|
|
43
|
+
@state.value[:queue].length
|
|
41
44
|
end
|
|
42
45
|
|
|
43
46
|
def shutdown
|
|
44
|
-
|
|
47
|
+
already_shutdown = false
|
|
48
|
+
@state.swap do |current_state|
|
|
49
|
+
if current_state[:shutdown]
|
|
50
|
+
already_shutdown = true
|
|
51
|
+
current_state
|
|
52
|
+
else
|
|
53
|
+
current_state.merge(shutdown: true)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
return if already_shutdown
|
|
57
|
+
|
|
58
|
+
Thread.pass until @state.value[:queue].empty?
|
|
59
|
+
|
|
45
60
|
@threads.each(&:join)
|
|
46
|
-
true
|
|
47
61
|
end
|
|
48
62
|
|
|
49
63
|
private
|
|
50
64
|
|
|
51
65
|
def start
|
|
52
|
-
@
|
|
53
|
-
Thread.new(num) do |idx|
|
|
66
|
+
@size.times do |num|
|
|
67
|
+
@threads << Thread.new(num) do |idx|
|
|
54
68
|
thread_name = String.new("AtomicThreadPool thread #{idx}")
|
|
55
69
|
thread_name << " for #{@name}" if @name
|
|
56
70
|
Thread.current.name = thread_name
|
|
@@ -59,9 +73,23 @@ module AtomicRuby
|
|
|
59
73
|
|
|
60
74
|
loop do
|
|
61
75
|
work = nil
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
76
|
+
should_shutdown = false
|
|
77
|
+
|
|
78
|
+
@state.swap do |current_state|
|
|
79
|
+
if current_state[:shutdown] && current_state[:queue].empty?
|
|
80
|
+
should_shutdown = true
|
|
81
|
+
current_state
|
|
82
|
+
elsif current_state[:queue].empty?
|
|
83
|
+
current_state
|
|
84
|
+
else
|
|
85
|
+
work = current_state[:queue].first
|
|
86
|
+
current_state.merge(queue: current_state[:queue].drop(1))
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
if should_shutdown
|
|
91
|
+
break
|
|
92
|
+
elsif work
|
|
65
93
|
begin
|
|
66
94
|
work.call
|
|
67
95
|
rescue => err
|
|
@@ -69,18 +97,13 @@ module AtomicRuby
|
|
|
69
97
|
puts "#{err.class}: #{err.message}"
|
|
70
98
|
puts err.backtrace.join("\n")
|
|
71
99
|
end
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
when NilClass
|
|
75
|
-
if @stopping.true?
|
|
76
|
-
break
|
|
77
|
-
else
|
|
78
|
-
Thread.pass
|
|
79
|
-
end
|
|
100
|
+
else
|
|
101
|
+
Thread.pass
|
|
80
102
|
end
|
|
81
103
|
end
|
|
82
104
|
end
|
|
83
105
|
end
|
|
106
|
+
@threads.freeze
|
|
84
107
|
|
|
85
108
|
Thread.pass until @started_threads.value == @size
|
|
86
109
|
end
|
data/lib/atomic-ruby/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: atomic-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joshua Young
|
|
@@ -50,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
50
50
|
- !ruby/object:Gem::Version
|
|
51
51
|
version: '0'
|
|
52
52
|
requirements: []
|
|
53
|
-
rubygems_version: 3.
|
|
53
|
+
rubygems_version: 3.7.2
|
|
54
54
|
specification_version: 4
|
|
55
55
|
summary: Atomic primitives for Ruby
|
|
56
56
|
test_files: []
|