Skip to content

Commit bab5fa1

Browse files
committed
Merge branch 'master' into refactor/tasks
2 parents fe52dde + 96fae99 commit bab5fa1

File tree

12 files changed

+504
-406
lines changed

12 files changed

+504
-406
lines changed
Lines changed: 96 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,87 @@
11
module Concurrent
22

3-
# @!visibility private
4-
module MutexAtomicFixnum # :nodoc:
3+
# @!macro [attach] atomic_fixnum
4+
#
5+
# A numeric value that can be updated atomically. Reads and writes to an atomic
6+
# fixnum and thread-safe and guaranteed to succeed. Reads and writes may block
7+
# briefly but no explicit locking is required.
8+
#
9+
# @since 0.5.0
10+
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong
11+
class MutexAtomicFixnum
512

6-
def allocate_storage(init)
13+
# @!macro [attach] atomic_fixnum_method_initialize
14+
#
15+
# Creates a new `AtomicFixnum` with the given initial value.
16+
#
17+
# @param [Fixnum] init the initial value
18+
# @raise [ArgumentError] if the initial value is not a `Fixnum`
19+
def initialize(init = 0)
20+
raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
721
@value = init
822
@mutex = Mutex.new
923
end
1024

25+
# @!macro [attach] atomic_fixnum_method_value
26+
#
27+
# Retrieves the current `Fixnum` value.
28+
#
29+
# @return [Fixnum] the current value
1130
def value
1231
@mutex.synchronize do
1332
@value
1433
end
1534
end
1635

36+
# @!macro [attach] atomic_fixnum_method_value_eq
37+
#
38+
# Explicitly sets the value.
39+
#
40+
# @param [Fixnum] value the new value to be set
41+
#
42+
# @return [Fixnum] the current value
43+
#
44+
# @raise [ArgumentError] if the new value is not a `Fixnum`
1745
def value=(value)
1846
raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
1947
@mutex.synchronize do
2048
@value = value
2149
end
2250
end
2351

52+
# @!macro [attach] atomic_fixnum_method_increment
53+
#
54+
# Increases the current value by 1.
55+
#
56+
# @return [Fixnum] the current value after incrementation
2457
def increment
2558
@mutex.synchronize do
2659
@value += 1
2760
end
2861
end
62+
alias_method :up, :increment
2963

64+
# @!macro [attach] atomic_fixnum_method_decrement
65+
#
66+
# Decreases the current value by 1.
67+
#
68+
# @return [Fixnum] the current value after decrementation
3069
def decrement
3170
@mutex.synchronize do
3271
@value -= 1
3372
end
3473
end
74+
alias_method :down, :decrement
3575

76+
# @!macro [attach] atomic_fixnum_method_compare_and_set
77+
#
78+
# Atomically sets the value to the given updated value if the current
79+
# value == the expected value.
80+
#
81+
# @param [Fixnum] expect the expected value
82+
# @param [Fixnum] update the new value
83+
#
84+
# @return [Boolean] true if the value was updated else false
3685
def compare_and_set(expect, update)
3786
@mutex.synchronize do
3887
if @value == expect
@@ -45,77 +94,60 @@ def compare_and_set(expect, update)
4594
end
4695
end
4796

48-
# @!visibility private
49-
module JavaAtomicFixnum # :nodoc:
97+
if RUBY_PLATFORM == 'java'
5098

51-
def allocate_storage(init)
52-
@atomic = java.util.concurrent.atomic.AtomicLong.new(init)
53-
end
99+
# @!macro atomic_fixnum
100+
class JavaAtomicFixnum
54101

55-
def value
56-
@atomic.get
57-
end
58-
59-
def value=(value)
60-
raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
61-
@atomic.set(value)
62-
end
102+
# @!macro atomic_fixnum_method_initialize
103+
#
104+
def initialize(init = 0)
105+
raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
106+
@atomic = java.util.concurrent.atomic.AtomicLong.new(init)
107+
end
63108

64-
def increment
65-
@atomic.increment_and_get
66-
end
109+
# @!macro atomic_fixnum_method_value
110+
#
111+
def value
112+
@atomic.get
113+
end
67114

68-
def decrement
69-
@atomic.decrement_and_get
70-
end
115+
# @!macro atomic_fixnum_method_value_eq
116+
#
117+
def value=(value)
118+
raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
119+
@atomic.set(value)
120+
end
71121

72-
def compare_and_set(expect, update)
73-
@atomic.compare_and_set(expect, update)
74-
end
75-
end
122+
# @!macro atomic_fixnum_method_increment
123+
#
124+
def increment
125+
@atomic.increment_and_get
126+
end
127+
alias_method :up, :increment
76128

77-
# A numeric value that can be updated atomically. Reads and writes to an atomic
78-
# fixnum and thread-safe and guaranteed to succeed. Reads and writes may block
79-
# briefly but no explicit locking is required.
80-
#
81-
# @!method value()
82-
# Retrieves the current `Fixnum` value
83-
# @return [Fixnum] the current value
84-
#
85-
# @!method value=(value)
86-
# Explicitly sets the value
87-
# @param [Fixnum] value the new value to be set
88-
# @return [Fixnum] the current value
89-
# @raise [ArgumentError] if the new value is not a `Fixnum`
90-
#
91-
# @!method increment()
92-
# Increases the current value by 1
93-
# @return [Fixnum] the current value after incrementation
94-
#
95-
# @!method decrement()
96-
# Decreases the current value by 1
97-
# @return [Fixnum] the current value after decrementation
98-
#
99-
# @since 0.5.0
100-
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong
101-
class AtomicFixnum
129+
# @!macro atomic_fixnum_method_decrement
130+
#
131+
def decrement
132+
@atomic.decrement_and_get
133+
end
134+
alias_method :down, :decrement
102135

103-
# Creates a new `AtomicFixnum` with the given initial value.
104-
#
105-
# @param [Fixnum] init the initial value
106-
# @raise [ArgumentError] if the initial value is not a `Fixnum`
107-
def initialize(init = 0)
108-
raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
109-
allocate_storage(init)
136+
# @!macro atomic_fixnum_method_compare_and_set
137+
#
138+
def compare_and_set(expect, update)
139+
@atomic.compare_and_set(expect, update)
140+
end
110141
end
111142

112-
if RUBY_PLATFORM == 'java'
113-
include JavaAtomicFixnum
114-
else
115-
include MutexAtomicFixnum
143+
# @!macro atomic_fixnum
144+
class AtomicFixnum < JavaAtomicFixnum
116145
end
117146

118-
alias_method :up, :increment
119-
alias_method :down, :decrement
147+
else
148+
149+
# @!macro atomic_fixnum
150+
class AtomicFixnum < MutexAtomicFixnum
151+
end
120152
end
121153
end

lib/concurrent/atomic/count_down_latch.rb

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,24 @@
22

33
module Concurrent
44

5-
# A synchronization object that allows one thread to wait on multiple other threads.
6-
# The thread that will wait creates a `CountDownLatch` and sets the initial value
7-
# (normally equal to the number of other threads). The initiating thread passes the
8-
# latch to the other threads then waits for the other threads by calling the `#wait`
9-
# method. Each of the other threads calls `#count_down` when done with its work.
10-
# When the latch counter reaches zero the waiting thread is unblocked and continues
11-
# with its work. A `CountDownLatch` can be used only once. Its value cannot be reset.
12-
class CountDownLatch
5+
# @!macro [attach] count_down_latch
6+
#
7+
# A synchronization object that allows one thread to wait on multiple other threads.
8+
# The thread that will wait creates a `CountDownLatch` and sets the initial value
9+
# (normally equal to the number of other threads). The initiating thread passes the
10+
# latch to the other threads then waits for the other threads by calling the `#wait`
11+
# method. Each of the other threads calls `#count_down` when done with its work.
12+
# When the latch counter reaches zero the waiting thread is unblocked and continues
13+
# with its work. A `CountDownLatch` can be used only once. Its value cannot be reset.
14+
class MutexCountDownLatch
1315

14-
# Create a new `CountDownLatch` with the initial `count`.
16+
# @!macro [attach] count_down_latch_method_initialize
1517
#
16-
# @param [Fixnum] count the initial count
18+
# Create a new `CountDownLatch` with the initial `count`.
1719
#
18-
# @raise [ArgumentError] if `count` is not an integer or is less than zero
20+
# @param [Fixnum] count the initial count
21+
#
22+
# @raise [ArgumentError] if `count` is not an integer or is less than zero
1923
def initialize(count)
2024
unless count.is_a?(Fixnum) && count >= 0
2125
raise ArgumentError.new('count must be in integer greater than or equal zero')
@@ -25,11 +29,13 @@ def initialize(count)
2529
@count = count
2630
end
2731

28-
# Block on the latch until the counter reaches zero or until `timeout` is reached.
32+
# @!macro [attach] count_down_latch_method_wait
33+
#
34+
# Block on the latch until the counter reaches zero or until `timeout` is reached.
2935
#
30-
# @param [Fixnum] timeout the number of seconds to wait for the counter or `nil`
31-
# to block indefinitely
32-
# @return [Boolean] `true` if the `count` reaches zero else false on `timeout`
36+
# @param [Fixnum] timeout the number of seconds to wait for the counter or `nil`
37+
# to block indefinitely
38+
# @return [Boolean] `true` if the `count` reaches zero else false on `timeout`
3339
def wait(timeout = nil)
3440
@mutex.synchronize do
3541

@@ -42,21 +48,69 @@ def wait(timeout = nil)
4248
end
4349
end
4450

45-
# Signal the latch to decrement the counter. Will signal all blocked threads when
46-
# the `count` reaches zero.
51+
# @!macro [attach] count_down_latch_method_count_down
52+
#
53+
# Signal the latch to decrement the counter. Will signal all blocked threads when
54+
# the `count` reaches zero.
4755
def count_down
4856
@mutex.synchronize do
4957
@count -= 1 if @count > 0
5058
@condition.broadcast if @count == 0
5159
end
5260
end
5361

54-
# The current value of the counter.
62+
# @!macro [attach] count_down_latch_method_count
5563
#
56-
# @return [Fixnum] the current value of the counter
64+
# The current value of the counter.
65+
#
66+
# @return [Fixnum] the current value of the counter
5767
def count
5868
@mutex.synchronize { @count }
5969
end
70+
end
71+
72+
if RUBY_PLATFORM == 'java'
73+
74+
# @!macro count_down_latch
75+
class JavaCountDownLatch
76+
77+
# @!macro count_down_latch_method_initialize
78+
def initialize(count)
79+
unless count.is_a?(Fixnum) && count >= 0
80+
raise ArgumentError.new('count must be in integer greater than or equal zero')
81+
end
82+
@latch = java.util.concurrent.CountDownLatch.new(count)
83+
end
84+
85+
# @!macro count_down_latch_method_wait
86+
def wait(timeout = nil)
87+
if timeout.nil?
88+
@latch.await
89+
true
90+
else
91+
@latch.await(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
92+
end
93+
end
94+
95+
# @!macro count_down_latch_method_count_down
96+
def count_down
97+
@latch.countDown
98+
end
99+
100+
# @!macro count_down_latch_method_count
101+
def count
102+
@latch.getCount
103+
end
104+
end
105+
106+
# @!macro count_down_latch
107+
class CountDownLatch < JavaCountDownLatch
108+
end
60109

110+
else
111+
112+
# @!macro count_down_latch
113+
class CountDownLatch < MutexCountDownLatch
114+
end
61115
end
62116
end

lib/concurrent/channels.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
require 'concurrent/collections'
2+
13
require 'concurrent/channel/channel'
24
require 'concurrent/channel/unbuffered_channel'
35
require 'concurrent/channel/buffered_channel'
4-
require 'concurrent/channel/ring_buffer'
5-
require 'concurrent/channel/blocking_ring_buffer'

lib/concurrent/channel/blocking_ring_buffer.rb renamed to lib/concurrent/collection/blocking_ring_buffer.rb

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,38 @@ def initialize(capacity)
1111
@condition = Condition.new
1212
end
1313

14+
# @return [Integer] the capacity of the buffer
1415
def capacity
1516
@mutex.synchronize { @buffer.capacity }
1617
end
1718

19+
# @return [Integer] the number of elements currently in the buffer
1820
def count
1921
@mutex.synchronize { @buffer.count }
2022
end
2123

22-
def full?
23-
@mutex.synchronize { @buffer.full? }
24-
end
25-
24+
# @return [Boolean] true if buffer is empty, false otherwise
2625
def empty?
2726
@mutex.synchronize { @buffer.empty? }
2827
end
2928

29+
# @return [Boolean] true if buffer is full, false otherwise
30+
def full?
31+
@mutex.synchronize { @buffer.full? }
32+
end
33+
34+
# @param [Object] value. This methods blocks until an empty slot is available
35+
# @return [Boolean] true if value has been inserted, false otherwise
3036
def put(value)
3137
@mutex.synchronize do
3238
wait_while_full
3339
@buffer.offer(value)
3440
@condition.signal
41+
true
3542
end
3643
end
3744

45+
# @return [Object] the first available value and removes it from the buffer. If buffer is empty it blocks until an element is available
3846
def take
3947
@mutex.synchronize do
4048
wait_while_empty
@@ -44,6 +52,7 @@ def take
4452
end
4553
end
4654

55+
# @return [Object] the first available value and without removing it from the buffer. If buffer is empty returns nil
4756
def peek
4857
@mutex.synchronize { @buffer.peek }
4958
end

0 commit comments

Comments
 (0)