concurrent-ruby 0.6.0.pre.1 → 0.6.0.pre.2
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/README.md +16 -0
- data/lib/concurrent.rb +9 -29
- data/lib/concurrent/{actor.rb → actor/actor.rb} +3 -3
- data/lib/concurrent/actor/actor_context.rb +77 -0
- data/lib/concurrent/actor/actor_ref.rb +67 -0
- data/lib/concurrent/{postable.rb → actor/postable.rb} +1 -1
- data/lib/concurrent/actor/simple_actor_ref.rb +94 -0
- data/lib/concurrent/actors.rb +5 -0
- data/lib/concurrent/agent.rb +81 -47
- data/lib/concurrent/async.rb +35 -35
- data/lib/concurrent/atomic/atomic_boolean.rb +157 -0
- data/lib/concurrent/atomic/atomic_fixnum.rb +170 -0
- data/lib/concurrent/{condition.rb → atomic/condition.rb} +0 -0
- data/lib/concurrent/{copy_on_notify_observer_set.rb → atomic/copy_on_notify_observer_set.rb} +48 -13
- data/lib/concurrent/{copy_on_write_observer_set.rb → atomic/copy_on_write_observer_set.rb} +41 -20
- data/lib/concurrent/atomic/count_down_latch.rb +116 -0
- data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
- data/lib/concurrent/atomic/event.rb +103 -0
- data/lib/concurrent/{thread_local_var.rb → atomic/thread_local_var.rb} +0 -0
- data/lib/concurrent/atomics.rb +9 -0
- data/lib/concurrent/channel/buffered_channel.rb +6 -4
- data/lib/concurrent/channel/channel.rb +30 -2
- data/lib/concurrent/channel/unbuffered_channel.rb +2 -2
- data/lib/concurrent/channel/waitable_list.rb +3 -1
- data/lib/concurrent/channels.rb +5 -0
- data/lib/concurrent/{channel → collection}/blocking_ring_buffer.rb +16 -5
- data/lib/concurrent/collection/priority_queue.rb +305 -0
- data/lib/concurrent/{channel → collection}/ring_buffer.rb +6 -1
- data/lib/concurrent/collections.rb +3 -0
- data/lib/concurrent/configuration.rb +68 -19
- data/lib/concurrent/dataflow.rb +9 -9
- data/lib/concurrent/delay.rb +21 -13
- data/lib/concurrent/dereferenceable.rb +40 -33
- data/lib/concurrent/exchanger.rb +3 -0
- data/lib/concurrent/{cached_thread_pool.rb → executor/cached_thread_pool.rb} +8 -9
- data/lib/concurrent/executor/executor.rb +222 -0
- data/lib/concurrent/{fixed_thread_pool.rb → executor/fixed_thread_pool.rb} +6 -7
- data/lib/concurrent/{immediate_executor.rb → executor/immediate_executor.rb} +5 -5
- data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
- data/lib/concurrent/{java_fixed_thread_pool.rb → executor/java_fixed_thread_pool.rb} +7 -11
- data/lib/concurrent/executor/java_single_thread_executor.rb +21 -0
- data/lib/concurrent/{java_thread_pool_executor.rb → executor/java_thread_pool_executor.rb} +66 -77
- data/lib/concurrent/executor/one_by_one.rb +65 -0
- data/lib/concurrent/{per_thread_executor.rb → executor/per_thread_executor.rb} +4 -4
- data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
- data/lib/concurrent/{ruby_fixed_thread_pool.rb → executor/ruby_fixed_thread_pool.rb} +5 -4
- data/lib/concurrent/executor/ruby_single_thread_executor.rb +72 -0
- data/lib/concurrent/executor/ruby_thread_pool_executor.rb +282 -0
- data/lib/concurrent/{ruby_thread_pool_worker.rb → executor/ruby_thread_pool_worker.rb} +6 -6
- data/lib/concurrent/{safe_task_executor.rb → executor/safe_task_executor.rb} +20 -13
- data/lib/concurrent/executor/single_thread_executor.rb +35 -0
- data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
- data/lib/concurrent/executor/timer_set.rb +138 -0
- data/lib/concurrent/executors.rb +9 -0
- data/lib/concurrent/future.rb +39 -40
- data/lib/concurrent/ivar.rb +22 -15
- data/lib/concurrent/mvar.rb +2 -1
- data/lib/concurrent/obligation.rb +9 -3
- data/lib/concurrent/observable.rb +33 -0
- data/lib/concurrent/options_parser.rb +46 -0
- data/lib/concurrent/promise.rb +23 -24
- data/lib/concurrent/scheduled_task.rb +21 -45
- data/lib/concurrent/timer_task.rb +204 -126
- data/lib/concurrent/tvar.rb +1 -1
- data/lib/concurrent/utilities.rb +3 -36
- data/lib/concurrent/{processor_count.rb → utility/processor_count.rb} +1 -1
- data/lib/concurrent/utility/timeout.rb +36 -0
- data/lib/concurrent/utility/timer.rb +21 -0
- data/lib/concurrent/version.rb +1 -1
- data/lib/concurrent_ruby_ext.bundle +0 -0
- data/spec/concurrent/{actor_context_spec.rb → actor/actor_context_spec.rb} +0 -8
- data/spec/concurrent/{actor_ref_shared.rb → actor/actor_ref_shared.rb} +9 -59
- data/spec/concurrent/{actor_spec.rb → actor/actor_spec.rb} +43 -41
- data/spec/concurrent/{postable_shared.rb → actor/postable_shared.rb} +0 -0
- data/spec/concurrent/actor/simple_actor_ref_spec.rb +135 -0
- data/spec/concurrent/agent_spec.rb +160 -71
- data/spec/concurrent/atomic/atomic_boolean_spec.rb +172 -0
- data/spec/concurrent/atomic/atomic_fixnum_spec.rb +186 -0
- data/spec/concurrent/{condition_spec.rb → atomic/condition_spec.rb} +2 -2
- data/spec/concurrent/{copy_on_notify_observer_set_spec.rb → atomic/copy_on_notify_observer_set_spec.rb} +0 -0
- data/spec/concurrent/{copy_on_write_observer_set_spec.rb → atomic/copy_on_write_observer_set_spec.rb} +0 -0
- data/spec/concurrent/atomic/count_down_latch_spec.rb +151 -0
- data/spec/concurrent/atomic/cyclic_barrier_spec.rb +248 -0
- data/spec/concurrent/{event_spec.rb → atomic/event_spec.rb} +18 -3
- data/spec/concurrent/{observer_set_shared.rb → atomic/observer_set_shared.rb} +15 -6
- data/spec/concurrent/{thread_local_var_spec.rb → atomic/thread_local_var_spec.rb} +0 -0
- data/spec/concurrent/channel/buffered_channel_spec.rb +1 -1
- data/spec/concurrent/channel/channel_spec.rb +6 -4
- data/spec/concurrent/channel/probe_spec.rb +37 -9
- data/spec/concurrent/channel/unbuffered_channel_spec.rb +2 -2
- data/spec/concurrent/{channel → collection}/blocking_ring_buffer_spec.rb +0 -0
- data/spec/concurrent/collection/priority_queue_spec.rb +317 -0
- data/spec/concurrent/{channel → collection}/ring_buffer_spec.rb +0 -0
- data/spec/concurrent/configuration_spec.rb +4 -70
- data/spec/concurrent/dereferenceable_shared.rb +5 -4
- data/spec/concurrent/exchanger_spec.rb +10 -5
- data/spec/concurrent/{cached_thread_pool_shared.rb → executor/cached_thread_pool_shared.rb} +15 -37
- data/spec/concurrent/{fixed_thread_pool_shared.rb → executor/fixed_thread_pool_shared.rb} +0 -0
- data/spec/concurrent/{global_thread_pool_shared.rb → executor/global_thread_pool_shared.rb} +10 -8
- data/spec/concurrent/{immediate_executor_spec.rb → executor/immediate_executor_spec.rb} +0 -0
- data/spec/concurrent/{java_cached_thread_pool_spec.rb → executor/java_cached_thread_pool_spec.rb} +1 -21
- data/spec/concurrent/{java_fixed_thread_pool_spec.rb → executor/java_fixed_thread_pool_spec.rb} +0 -0
- data/spec/concurrent/executor/java_single_thread_executor_spec.rb +21 -0
- data/spec/concurrent/{java_thread_pool_executor_spec.rb → executor/java_thread_pool_executor_spec.rb} +0 -0
- data/spec/concurrent/{per_thread_executor_spec.rb → executor/per_thread_executor_spec.rb} +0 -4
- data/spec/concurrent/{ruby_cached_thread_pool_spec.rb → executor/ruby_cached_thread_pool_spec.rb} +1 -1
- data/spec/concurrent/{ruby_fixed_thread_pool_spec.rb → executor/ruby_fixed_thread_pool_spec.rb} +0 -0
- data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +18 -0
- data/spec/concurrent/{ruby_thread_pool_executor_spec.rb → executor/ruby_thread_pool_executor_spec.rb} +12 -24
- data/spec/concurrent/executor/safe_task_executor_spec.rb +103 -0
- data/spec/concurrent/{thread_pool_class_cast_spec.rb → executor/thread_pool_class_cast_spec.rb} +12 -0
- data/spec/concurrent/{thread_pool_executor_shared.rb → executor/thread_pool_executor_shared.rb} +0 -0
- data/spec/concurrent/{thread_pool_shared.rb → executor/thread_pool_shared.rb} +84 -119
- data/spec/concurrent/executor/timer_set_spec.rb +183 -0
- data/spec/concurrent/future_spec.rb +12 -0
- data/spec/concurrent/ivar_spec.rb +11 -1
- data/spec/concurrent/observable_shared.rb +173 -0
- data/spec/concurrent/observable_spec.rb +51 -0
- data/spec/concurrent/options_parser_spec.rb +71 -0
- data/spec/concurrent/runnable_shared.rb +6 -0
- data/spec/concurrent/scheduled_task_spec.rb +60 -40
- data/spec/concurrent/timer_task_spec.rb +130 -144
- data/spec/concurrent/{processor_count_spec.rb → utility/processor_count_spec.rb} +0 -0
- data/spec/concurrent/{utilities_spec.rb → utility/timeout_spec.rb} +0 -0
- data/spec/concurrent/utility/timer_spec.rb +52 -0
- metadata +147 -108
- data/lib/concurrent/actor_context.rb +0 -31
- data/lib/concurrent/actor_ref.rb +0 -39
- data/lib/concurrent/atomic.rb +0 -121
- data/lib/concurrent/channel/probe.rb +0 -19
- data/lib/concurrent/count_down_latch.rb +0 -60
- data/lib/concurrent/event.rb +0 -80
- data/lib/concurrent/java_cached_thread_pool.rb +0 -45
- data/lib/concurrent/ruby_cached_thread_pool.rb +0 -37
- data/lib/concurrent/ruby_thread_pool_executor.rb +0 -268
- data/lib/concurrent/simple_actor_ref.rb +0 -124
- data/lib/concurrent/thread_pool_executor.rb +0 -30
- data/spec/concurrent/atomic_spec.rb +0 -201
- data/spec/concurrent/count_down_latch_spec.rb +0 -125
- data/spec/concurrent/safe_task_executor_spec.rb +0 -58
- data/spec/concurrent/simple_actor_ref_spec.rb +0 -219
@@ -21,7 +21,6 @@ module Concurrent
|
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'returns false if the event is unset' do
|
24
|
-
#subject.reset
|
25
24
|
subject.should_not be_set
|
26
25
|
end
|
27
26
|
end
|
@@ -29,7 +28,6 @@ module Concurrent
|
|
29
28
|
context '#set' do
|
30
29
|
|
31
30
|
it 'triggers the event' do
|
32
|
-
#subject.reset
|
33
31
|
@expected = false
|
34
32
|
Thread.new{ subject.wait; @expected = true }
|
35
33
|
sleep(0.1)
|
@@ -44,13 +42,30 @@ module Concurrent
|
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
45
|
+
context '#try?' do
|
46
|
+
|
47
|
+
it 'triggers the event if not already set' do
|
48
|
+
subject.try?
|
49
|
+
subject.should be_set
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'returns true if not previously set' do
|
53
|
+
subject.try?.should be_true
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'returns false if previously set' do
|
57
|
+
subject.set
|
58
|
+
subject.try?.should be_false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
47
62
|
context '#reset' do
|
48
63
|
|
49
64
|
it 'does not change the state of an unset event' do
|
50
65
|
subject.reset
|
51
66
|
subject.should_not be_set
|
52
67
|
end
|
53
|
-
|
68
|
+
|
54
69
|
it 'does not trigger an unset event' do
|
55
70
|
@expected = false
|
56
71
|
Thread.new{ subject.wait; @expected = true }
|
@@ -8,15 +8,16 @@ shared_examples "an observer set" do
|
|
8
8
|
|
9
9
|
describe '#add_observer' do
|
10
10
|
|
11
|
-
context 'with
|
12
|
-
it 'should return the
|
13
|
-
observer_set.add_observer(observer, :a_method).should
|
11
|
+
context 'with arguments' do
|
12
|
+
it 'should return the observer' do
|
13
|
+
observer_set.add_observer(observer, :a_method).should == observer
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
context '
|
18
|
-
it 'should return the
|
19
|
-
observer_set.add_observer
|
17
|
+
context 'with a block' do
|
18
|
+
it 'should return the observer based on a block' do
|
19
|
+
observer = observer_set.add_observer { :block }
|
20
|
+
observer.call.should == :block
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
@@ -61,6 +62,14 @@ shared_examples "an observer set" do
|
|
61
62
|
observer_set.notify_observers('a string arg')
|
62
63
|
end
|
63
64
|
|
65
|
+
it 'should notify an observer from a block' do
|
66
|
+
notification = double
|
67
|
+
expect(notification).to receive(:catch)
|
68
|
+
|
69
|
+
observer_set.add_observer {|arg| arg.catch }
|
70
|
+
observer_set.notify_observers notification
|
71
|
+
end
|
72
|
+
|
64
73
|
it 'can be called many times' do
|
65
74
|
expect(observer).to receive(:update).with(:an_arg).twice
|
66
75
|
expect(observer).to receive(:update).with(no_args).once
|
File without changes
|
@@ -12,22 +12,24 @@ module Concurrent
|
|
12
12
|
|
13
13
|
Thread.new { channels[1].push 77 }
|
14
14
|
|
15
|
-
value = Channel.select(*channels)
|
15
|
+
value, channel = Channel.select(*channels)
|
16
16
|
|
17
17
|
value.should eq 77
|
18
|
+
channel.should be channels[1]
|
18
19
|
end
|
19
20
|
|
20
21
|
it 'cleans up' do
|
21
22
|
channels = [ UnbufferedChannel.new, UnbufferedChannel.new]
|
22
|
-
channels.each { |ch| ch.stub(:remove_probe).with( an_instance_of(Probe) )}
|
23
|
+
channels.each { |ch| ch.stub(:remove_probe).with( an_instance_of(Channel::Probe) )}
|
23
24
|
|
24
25
|
Thread.new { channels[1].push 77 }
|
25
26
|
|
26
|
-
value = Channel.select(*channels)
|
27
|
+
value, channel = Channel.select(*channels)
|
27
28
|
|
28
29
|
value.should eq 77
|
30
|
+
channel.should be channels[1]
|
29
31
|
|
30
|
-
channels.each { |ch| expect(ch).to have_received(:remove_probe).with( an_instance_of(Probe) ) }
|
32
|
+
channels.each { |ch| expect(ch).to have_received(:remove_probe).with( an_instance_of(Channel::Probe) ) }
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
@@ -1,33 +1,53 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require_relative '../observable_shared'
|
2
3
|
|
3
4
|
module Concurrent
|
4
5
|
|
5
|
-
describe Probe do
|
6
|
+
describe Channel::Probe do
|
6
7
|
|
7
|
-
let(:
|
8
|
+
let(:channel) { Object.new }
|
9
|
+
let(:probe) { Channel::Probe.new }
|
10
|
+
|
11
|
+
describe 'behavior' do
|
12
|
+
|
13
|
+
# observable
|
14
|
+
|
15
|
+
subject{ Channel::Probe.new }
|
16
|
+
|
17
|
+
def trigger_observable(observable)
|
18
|
+
observable.set('value')
|
19
|
+
end
|
20
|
+
|
21
|
+
it_should_behave_like :observable
|
22
|
+
end
|
8
23
|
|
9
24
|
describe '#set_unless_assigned' do
|
10
25
|
context 'empty probe' do
|
11
26
|
it 'assigns the value' do
|
12
|
-
probe.set_unless_assigned(32)
|
27
|
+
probe.set_unless_assigned(32, channel)
|
13
28
|
probe.value.should eq 32
|
14
29
|
end
|
15
30
|
|
31
|
+
it 'assign the channel' do
|
32
|
+
probe.set_unless_assigned(32, channel)
|
33
|
+
probe.channel.should be channel
|
34
|
+
end
|
35
|
+
|
16
36
|
it 'returns true' do
|
17
|
-
probe.set_unless_assigned('hi').should eq true
|
37
|
+
probe.set_unless_assigned('hi', channel).should eq true
|
18
38
|
end
|
19
39
|
end
|
20
40
|
|
21
41
|
context 'fulfilled probe' do
|
22
|
-
before(:each) { probe.set(27) }
|
42
|
+
before(:each) { probe.set([27, nil]) }
|
23
43
|
|
24
44
|
it 'does not assign the value' do
|
25
|
-
probe.set_unless_assigned(88)
|
45
|
+
probe.set_unless_assigned(88, channel)
|
26
46
|
probe.value.should eq 27
|
27
47
|
end
|
28
48
|
|
29
49
|
it 'returns false' do
|
30
|
-
probe.set_unless_assigned('hello').should eq false
|
50
|
+
probe.set_unless_assigned('hello', channel).should eq false
|
31
51
|
end
|
32
52
|
end
|
33
53
|
|
@@ -35,12 +55,20 @@ module Concurrent
|
|
35
55
|
before(:each) { probe.fail }
|
36
56
|
|
37
57
|
it 'does not assign the value' do
|
38
|
-
probe.set_unless_assigned(88)
|
58
|
+
probe.set_unless_assigned(88, channel)
|
39
59
|
probe.should be_rejected
|
40
60
|
end
|
41
61
|
|
62
|
+
it 'has a nil value' do
|
63
|
+
probe.value.should be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'has a nil channel' do
|
67
|
+
probe.channel.should be_nil
|
68
|
+
end
|
69
|
+
|
42
70
|
it 'returns false' do
|
43
|
-
probe.set_unless_assigned('hello').should eq false
|
71
|
+
probe.set_unless_assigned('hello', channel).should eq false
|
44
72
|
end
|
45
73
|
end
|
46
74
|
end
|
@@ -5,7 +5,7 @@ module Concurrent
|
|
5
5
|
describe UnbufferedChannel do
|
6
6
|
|
7
7
|
let!(:channel) { subject }
|
8
|
-
let(:probe) { Probe.new }
|
8
|
+
let(:probe) { Channel::Probe.new }
|
9
9
|
|
10
10
|
context 'with one thread' do
|
11
11
|
|
@@ -97,7 +97,7 @@ module Concurrent
|
|
97
97
|
|
98
98
|
t.status.should eq 'sleep'
|
99
99
|
|
100
|
-
new_probe = Probe.new
|
100
|
+
new_probe = Channel::Probe.new
|
101
101
|
|
102
102
|
channel.select(new_probe)
|
103
103
|
|
File without changes
|
@@ -0,0 +1,317 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
share_examples_for :priority_queue do
|
4
|
+
|
5
|
+
subject{ described_class.new }
|
6
|
+
|
7
|
+
context '#initialize' do
|
8
|
+
|
9
|
+
it 'sorts from high to low when :order is :max' do
|
10
|
+
subject = described_class.from_list([2, 1, 4, 5, 3, 0], order: :max)
|
11
|
+
subject.pop.should eq 5
|
12
|
+
subject.pop.should eq 4
|
13
|
+
subject.pop.should eq 3
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'sorts from high to low when :order is :high' do
|
17
|
+
subject = described_class.new(order: :high)
|
18
|
+
[2, 1, 4, 5, 3, 0].each{|item| subject << item }
|
19
|
+
subject.pop.should eq 5
|
20
|
+
subject.pop.should eq 4
|
21
|
+
subject.pop.should eq 3
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'sorts from low to high when :order is :min' do
|
25
|
+
subject = described_class.from_list([2, 1, 4, 5, 3, 0], order: :min)
|
26
|
+
subject.pop.should eq 0
|
27
|
+
subject.pop.should eq 1
|
28
|
+
subject.pop.should eq 2
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'sorts from low to high when :order is :low' do
|
32
|
+
subject = described_class.new(order: :low)
|
33
|
+
[2, 1, 4, 5, 3, 0].each{|item| subject << item }
|
34
|
+
subject.pop.should eq 0
|
35
|
+
subject.pop.should eq 1
|
36
|
+
subject.pop.should eq 2
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'sorts from high to low by default' do
|
40
|
+
subject = described_class.new
|
41
|
+
subject = described_class.from_list([2, 1, 4, 5, 3, 0])
|
42
|
+
subject.pop.should eq 5
|
43
|
+
subject.pop.should eq 4
|
44
|
+
subject.pop.should eq 3
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context '#clear' do
|
49
|
+
|
50
|
+
it 'removes all items from a populated queue' do
|
51
|
+
10.times{|i| subject << i}
|
52
|
+
subject.clear
|
53
|
+
subject.should be_empty
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'has no effect on an empty queue' do
|
57
|
+
subject.clear
|
58
|
+
subject.should be_empty
|
59
|
+
end
|
60
|
+
|
61
|
+
specify { subject.clear.should be_true }
|
62
|
+
end
|
63
|
+
|
64
|
+
context '#delete' do
|
65
|
+
|
66
|
+
it 'deletes the requested item when found' do
|
67
|
+
10.times{|item| subject << item }
|
68
|
+
subject.delete(5)
|
69
|
+
subject.pop.should eq 9
|
70
|
+
subject.pop.should eq 8
|
71
|
+
subject.pop.should eq 7
|
72
|
+
subject.pop.should eq 6
|
73
|
+
subject.pop.should eq 4
|
74
|
+
subject.pop.should eq 3
|
75
|
+
subject.pop.should eq 2
|
76
|
+
subject.pop.should eq 1
|
77
|
+
subject.pop.should eq 0
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'deletes the requested item when it is the first element' do
|
81
|
+
10.times{|item| subject << item }
|
82
|
+
subject.delete(9)
|
83
|
+
subject.length.should eq 9
|
84
|
+
subject.pop.should eq 8
|
85
|
+
subject.pop.should eq 7
|
86
|
+
subject.pop.should eq 6
|
87
|
+
subject.pop.should eq 5
|
88
|
+
subject.pop.should eq 4
|
89
|
+
subject.pop.should eq 3
|
90
|
+
subject.pop.should eq 2
|
91
|
+
subject.pop.should eq 1
|
92
|
+
subject.pop.should eq 0
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'deletes the requested item when it is the last element' do
|
96
|
+
10.times{|item| subject << item }
|
97
|
+
subject.delete(2)
|
98
|
+
subject.length.should eq 9
|
99
|
+
subject.pop.should eq 9
|
100
|
+
subject.pop.should eq 8
|
101
|
+
subject.pop.should eq 7
|
102
|
+
subject.pop.should eq 6
|
103
|
+
subject.pop.should eq 5
|
104
|
+
subject.pop.should eq 4
|
105
|
+
subject.pop.should eq 3
|
106
|
+
subject.pop.should eq 1
|
107
|
+
subject.pop.should eq 0
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'deletes multiple matching items when present' do
|
111
|
+
[2, 1, 2, 2, 2, 3, 2].each{|item| subject << item }
|
112
|
+
subject.delete(2)
|
113
|
+
subject.pop.should eq 3
|
114
|
+
subject.pop.should eq 1
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'returns true when found' do
|
118
|
+
10.times{|i| subject << i}
|
119
|
+
subject.delete(2).should be_true
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'returns false when not found' do
|
123
|
+
10.times{|i| subject << i}
|
124
|
+
subject.delete(100).should be_false
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'returns false when called on an empty queue' do
|
128
|
+
subject.delete(:foo).should be_false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context '#empty?' do
|
133
|
+
|
134
|
+
it 'returns true for an empty queue' do
|
135
|
+
subject.should be_empty
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'returns false for a populated queue' do
|
139
|
+
10.times{|i| subject << i}
|
140
|
+
subject.should_not be_empty
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context '#include?' do
|
145
|
+
|
146
|
+
it 'returns true if the item is found' do
|
147
|
+
10.times{|i| subject << i}
|
148
|
+
subject.should include(5)
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'returns false if the item is not found' do
|
152
|
+
10.times{|i| subject << i}
|
153
|
+
subject.should_not include(50)
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'returns false when the queue is empty' do
|
157
|
+
subject.should_not include(1)
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'is aliased as #has_priority?' do
|
161
|
+
10.times{|i| subject << i}
|
162
|
+
subject.should have_priority(5)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context '#length' do
|
167
|
+
|
168
|
+
it 'returns the length of a populated queue' do
|
169
|
+
10.times{|i| subject << i}
|
170
|
+
subject.length.should eq 10
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'returns zero when the queue is empty' do
|
174
|
+
subject.length.should eq 0
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'is aliased as #size' do
|
178
|
+
10.times{|i| subject << i}
|
179
|
+
subject.size.should eq 10
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context '#peek' do
|
184
|
+
|
185
|
+
it 'returns the item at the head of the queue' do
|
186
|
+
10.times{|i| subject << i}
|
187
|
+
subject.peek.should eq 9
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'does not remove the item from the queue' do
|
191
|
+
10.times{|i| subject << i}
|
192
|
+
subject.peek
|
193
|
+
subject.length.should eq 10
|
194
|
+
subject.should include(9)
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'returns nil when the queue is empty' do
|
198
|
+
subject.peek.should be_nil
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context '#pop' do
|
203
|
+
|
204
|
+
it 'returns the item at the head of the queue' do
|
205
|
+
10.times{|i| subject << i}
|
206
|
+
subject.pop.should eq 9
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'removes the item from the queue' do
|
210
|
+
10.times{|i| subject << i}
|
211
|
+
subject.pop
|
212
|
+
subject.length.should eq 9
|
213
|
+
subject.should_not include(9)
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'returns nil when the queue is empty' do
|
217
|
+
subject.pop.should be_nil
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'is aliased as #deq' do
|
221
|
+
10.times{|i| subject << i}
|
222
|
+
subject.deq.should eq 9
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'is aliased as #shift' do
|
226
|
+
10.times{|i| subject << i}
|
227
|
+
subject.shift.should eq 9
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context '#push' do
|
232
|
+
|
233
|
+
it 'adds the item to the queue' do
|
234
|
+
subject.push(1)
|
235
|
+
subject.should include(1)
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'sorts the new item in priority order' do
|
239
|
+
3.times{|i| subject << i}
|
240
|
+
subject.pop.should eq 2
|
241
|
+
subject.pop.should eq 1
|
242
|
+
subject.pop.should eq 0
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'arbitrarily orders equal items with respect to each other' do
|
246
|
+
3.times{|i| subject << i}
|
247
|
+
subject.push(1)
|
248
|
+
subject.pop.should eq 2
|
249
|
+
subject.pop.should eq 1
|
250
|
+
subject.pop.should eq 1
|
251
|
+
subject.pop.should eq 0
|
252
|
+
end
|
253
|
+
|
254
|
+
specify { subject.push(10).should be_true }
|
255
|
+
|
256
|
+
it 'is aliased as <<' do
|
257
|
+
subject << 1
|
258
|
+
subject.should include(1)
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'is aliased as enq' do
|
262
|
+
subject.enq(1)
|
263
|
+
subject.should include(1)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
context '.from_list' do
|
268
|
+
|
269
|
+
it 'creates an empty queue from an empty list' do
|
270
|
+
subject = described_class.from_list([])
|
271
|
+
subject.should be_empty
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'creates a sorted, populated queue from an Array' do
|
275
|
+
subject = described_class.from_list([2, 1, 4, 5, 3, 0])
|
276
|
+
subject.pop.should eq 5
|
277
|
+
subject.pop.should eq 4
|
278
|
+
subject.pop.should eq 3
|
279
|
+
subject.pop.should eq 2
|
280
|
+
subject.pop.should eq 1
|
281
|
+
subject.pop.should eq 0
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'creates a sorted, populated queue from a Hash' do
|
285
|
+
subject = described_class.from_list(two: 2, one: 1, three: 3, zero: 0)
|
286
|
+
subject.length.should eq 4
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
module Concurrent
|
292
|
+
|
293
|
+
describe MutexPriorityQueue do
|
294
|
+
|
295
|
+
it_should_behave_like :priority_queue
|
296
|
+
end
|
297
|
+
|
298
|
+
if jruby?
|
299
|
+
|
300
|
+
describe JavaPriorityQueue do
|
301
|
+
|
302
|
+
it_should_behave_like :priority_queue
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
describe PriorityQueue do
|
307
|
+
if jruby?
|
308
|
+
it 'inherits from JavaPriorityQueue' do
|
309
|
+
PriorityQueue.ancestors.should include(JavaPriorityQueue)
|
310
|
+
end
|
311
|
+
else
|
312
|
+
it 'inherits from MutexPriorityQueue' do
|
313
|
+
PriorityQueue.ancestors.should include(MutexPriorityQueue)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|