concurrent-ruby 0.6.0.pre.1 → 0.6.0.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|