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.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -0
  3. data/lib/concurrent.rb +9 -29
  4. data/lib/concurrent/{actor.rb → actor/actor.rb} +3 -3
  5. data/lib/concurrent/actor/actor_context.rb +77 -0
  6. data/lib/concurrent/actor/actor_ref.rb +67 -0
  7. data/lib/concurrent/{postable.rb → actor/postable.rb} +1 -1
  8. data/lib/concurrent/actor/simple_actor_ref.rb +94 -0
  9. data/lib/concurrent/actors.rb +5 -0
  10. data/lib/concurrent/agent.rb +81 -47
  11. data/lib/concurrent/async.rb +35 -35
  12. data/lib/concurrent/atomic/atomic_boolean.rb +157 -0
  13. data/lib/concurrent/atomic/atomic_fixnum.rb +170 -0
  14. data/lib/concurrent/{condition.rb → atomic/condition.rb} +0 -0
  15. data/lib/concurrent/{copy_on_notify_observer_set.rb → atomic/copy_on_notify_observer_set.rb} +48 -13
  16. data/lib/concurrent/{copy_on_write_observer_set.rb → atomic/copy_on_write_observer_set.rb} +41 -20
  17. data/lib/concurrent/atomic/count_down_latch.rb +116 -0
  18. data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
  19. data/lib/concurrent/atomic/event.rb +103 -0
  20. data/lib/concurrent/{thread_local_var.rb → atomic/thread_local_var.rb} +0 -0
  21. data/lib/concurrent/atomics.rb +9 -0
  22. data/lib/concurrent/channel/buffered_channel.rb +6 -4
  23. data/lib/concurrent/channel/channel.rb +30 -2
  24. data/lib/concurrent/channel/unbuffered_channel.rb +2 -2
  25. data/lib/concurrent/channel/waitable_list.rb +3 -1
  26. data/lib/concurrent/channels.rb +5 -0
  27. data/lib/concurrent/{channel → collection}/blocking_ring_buffer.rb +16 -5
  28. data/lib/concurrent/collection/priority_queue.rb +305 -0
  29. data/lib/concurrent/{channel → collection}/ring_buffer.rb +6 -1
  30. data/lib/concurrent/collections.rb +3 -0
  31. data/lib/concurrent/configuration.rb +68 -19
  32. data/lib/concurrent/dataflow.rb +9 -9
  33. data/lib/concurrent/delay.rb +21 -13
  34. data/lib/concurrent/dereferenceable.rb +40 -33
  35. data/lib/concurrent/exchanger.rb +3 -0
  36. data/lib/concurrent/{cached_thread_pool.rb → executor/cached_thread_pool.rb} +8 -9
  37. data/lib/concurrent/executor/executor.rb +222 -0
  38. data/lib/concurrent/{fixed_thread_pool.rb → executor/fixed_thread_pool.rb} +6 -7
  39. data/lib/concurrent/{immediate_executor.rb → executor/immediate_executor.rb} +5 -5
  40. data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
  41. data/lib/concurrent/{java_fixed_thread_pool.rb → executor/java_fixed_thread_pool.rb} +7 -11
  42. data/lib/concurrent/executor/java_single_thread_executor.rb +21 -0
  43. data/lib/concurrent/{java_thread_pool_executor.rb → executor/java_thread_pool_executor.rb} +66 -77
  44. data/lib/concurrent/executor/one_by_one.rb +65 -0
  45. data/lib/concurrent/{per_thread_executor.rb → executor/per_thread_executor.rb} +4 -4
  46. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
  47. data/lib/concurrent/{ruby_fixed_thread_pool.rb → executor/ruby_fixed_thread_pool.rb} +5 -4
  48. data/lib/concurrent/executor/ruby_single_thread_executor.rb +72 -0
  49. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +282 -0
  50. data/lib/concurrent/{ruby_thread_pool_worker.rb → executor/ruby_thread_pool_worker.rb} +6 -6
  51. data/lib/concurrent/{safe_task_executor.rb → executor/safe_task_executor.rb} +20 -13
  52. data/lib/concurrent/executor/single_thread_executor.rb +35 -0
  53. data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
  54. data/lib/concurrent/executor/timer_set.rb +138 -0
  55. data/lib/concurrent/executors.rb +9 -0
  56. data/lib/concurrent/future.rb +39 -40
  57. data/lib/concurrent/ivar.rb +22 -15
  58. data/lib/concurrent/mvar.rb +2 -1
  59. data/lib/concurrent/obligation.rb +9 -3
  60. data/lib/concurrent/observable.rb +33 -0
  61. data/lib/concurrent/options_parser.rb +46 -0
  62. data/lib/concurrent/promise.rb +23 -24
  63. data/lib/concurrent/scheduled_task.rb +21 -45
  64. data/lib/concurrent/timer_task.rb +204 -126
  65. data/lib/concurrent/tvar.rb +1 -1
  66. data/lib/concurrent/utilities.rb +3 -36
  67. data/lib/concurrent/{processor_count.rb → utility/processor_count.rb} +1 -1
  68. data/lib/concurrent/utility/timeout.rb +36 -0
  69. data/lib/concurrent/utility/timer.rb +21 -0
  70. data/lib/concurrent/version.rb +1 -1
  71. data/lib/concurrent_ruby_ext.bundle +0 -0
  72. data/spec/concurrent/{actor_context_spec.rb → actor/actor_context_spec.rb} +0 -8
  73. data/spec/concurrent/{actor_ref_shared.rb → actor/actor_ref_shared.rb} +9 -59
  74. data/spec/concurrent/{actor_spec.rb → actor/actor_spec.rb} +43 -41
  75. data/spec/concurrent/{postable_shared.rb → actor/postable_shared.rb} +0 -0
  76. data/spec/concurrent/actor/simple_actor_ref_spec.rb +135 -0
  77. data/spec/concurrent/agent_spec.rb +160 -71
  78. data/spec/concurrent/atomic/atomic_boolean_spec.rb +172 -0
  79. data/spec/concurrent/atomic/atomic_fixnum_spec.rb +186 -0
  80. data/spec/concurrent/{condition_spec.rb → atomic/condition_spec.rb} +2 -2
  81. data/spec/concurrent/{copy_on_notify_observer_set_spec.rb → atomic/copy_on_notify_observer_set_spec.rb} +0 -0
  82. data/spec/concurrent/{copy_on_write_observer_set_spec.rb → atomic/copy_on_write_observer_set_spec.rb} +0 -0
  83. data/spec/concurrent/atomic/count_down_latch_spec.rb +151 -0
  84. data/spec/concurrent/atomic/cyclic_barrier_spec.rb +248 -0
  85. data/spec/concurrent/{event_spec.rb → atomic/event_spec.rb} +18 -3
  86. data/spec/concurrent/{observer_set_shared.rb → atomic/observer_set_shared.rb} +15 -6
  87. data/spec/concurrent/{thread_local_var_spec.rb → atomic/thread_local_var_spec.rb} +0 -0
  88. data/spec/concurrent/channel/buffered_channel_spec.rb +1 -1
  89. data/spec/concurrent/channel/channel_spec.rb +6 -4
  90. data/spec/concurrent/channel/probe_spec.rb +37 -9
  91. data/spec/concurrent/channel/unbuffered_channel_spec.rb +2 -2
  92. data/spec/concurrent/{channel → collection}/blocking_ring_buffer_spec.rb +0 -0
  93. data/spec/concurrent/collection/priority_queue_spec.rb +317 -0
  94. data/spec/concurrent/{channel → collection}/ring_buffer_spec.rb +0 -0
  95. data/spec/concurrent/configuration_spec.rb +4 -70
  96. data/spec/concurrent/dereferenceable_shared.rb +5 -4
  97. data/spec/concurrent/exchanger_spec.rb +10 -5
  98. data/spec/concurrent/{cached_thread_pool_shared.rb → executor/cached_thread_pool_shared.rb} +15 -37
  99. data/spec/concurrent/{fixed_thread_pool_shared.rb → executor/fixed_thread_pool_shared.rb} +0 -0
  100. data/spec/concurrent/{global_thread_pool_shared.rb → executor/global_thread_pool_shared.rb} +10 -8
  101. data/spec/concurrent/{immediate_executor_spec.rb → executor/immediate_executor_spec.rb} +0 -0
  102. data/spec/concurrent/{java_cached_thread_pool_spec.rb → executor/java_cached_thread_pool_spec.rb} +1 -21
  103. data/spec/concurrent/{java_fixed_thread_pool_spec.rb → executor/java_fixed_thread_pool_spec.rb} +0 -0
  104. data/spec/concurrent/executor/java_single_thread_executor_spec.rb +21 -0
  105. data/spec/concurrent/{java_thread_pool_executor_spec.rb → executor/java_thread_pool_executor_spec.rb} +0 -0
  106. data/spec/concurrent/{per_thread_executor_spec.rb → executor/per_thread_executor_spec.rb} +0 -4
  107. data/spec/concurrent/{ruby_cached_thread_pool_spec.rb → executor/ruby_cached_thread_pool_spec.rb} +1 -1
  108. data/spec/concurrent/{ruby_fixed_thread_pool_spec.rb → executor/ruby_fixed_thread_pool_spec.rb} +0 -0
  109. data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +18 -0
  110. data/spec/concurrent/{ruby_thread_pool_executor_spec.rb → executor/ruby_thread_pool_executor_spec.rb} +12 -24
  111. data/spec/concurrent/executor/safe_task_executor_spec.rb +103 -0
  112. data/spec/concurrent/{thread_pool_class_cast_spec.rb → executor/thread_pool_class_cast_spec.rb} +12 -0
  113. data/spec/concurrent/{thread_pool_executor_shared.rb → executor/thread_pool_executor_shared.rb} +0 -0
  114. data/spec/concurrent/{thread_pool_shared.rb → executor/thread_pool_shared.rb} +84 -119
  115. data/spec/concurrent/executor/timer_set_spec.rb +183 -0
  116. data/spec/concurrent/future_spec.rb +12 -0
  117. data/spec/concurrent/ivar_spec.rb +11 -1
  118. data/spec/concurrent/observable_shared.rb +173 -0
  119. data/spec/concurrent/observable_spec.rb +51 -0
  120. data/spec/concurrent/options_parser_spec.rb +71 -0
  121. data/spec/concurrent/runnable_shared.rb +6 -0
  122. data/spec/concurrent/scheduled_task_spec.rb +60 -40
  123. data/spec/concurrent/timer_task_spec.rb +130 -144
  124. data/spec/concurrent/{processor_count_spec.rb → utility/processor_count_spec.rb} +0 -0
  125. data/spec/concurrent/{utilities_spec.rb → utility/timeout_spec.rb} +0 -0
  126. data/spec/concurrent/utility/timer_spec.rb +52 -0
  127. metadata +147 -108
  128. data/lib/concurrent/actor_context.rb +0 -31
  129. data/lib/concurrent/actor_ref.rb +0 -39
  130. data/lib/concurrent/atomic.rb +0 -121
  131. data/lib/concurrent/channel/probe.rb +0 -19
  132. data/lib/concurrent/count_down_latch.rb +0 -60
  133. data/lib/concurrent/event.rb +0 -80
  134. data/lib/concurrent/java_cached_thread_pool.rb +0 -45
  135. data/lib/concurrent/ruby_cached_thread_pool.rb +0 -37
  136. data/lib/concurrent/ruby_thread_pool_executor.rb +0 -268
  137. data/lib/concurrent/simple_actor_ref.rb +0 -124
  138. data/lib/concurrent/thread_pool_executor.rb +0 -30
  139. data/spec/concurrent/atomic_spec.rb +0 -201
  140. data/spec/concurrent/count_down_latch_spec.rb +0 -125
  141. data/spec/concurrent/safe_task_executor_spec.rb +0 -58
  142. 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 argument' do
12
- it 'should return the passed function' do
13
- observer_set.add_observer(observer, :a_method).should eq(:a_method)
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 'without arguments' do
18
- it 'should return the default function' do
19
- observer_set.add_observer(observer).should eq(:update)
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
@@ -6,7 +6,7 @@ module Concurrent
6
6
 
7
7
  let(:size) { 2 }
8
8
  let!(:channel) { BufferedChannel.new(size) }
9
- let(:probe) { Probe.new }
9
+ let(:probe) { Channel::Probe.new }
10
10
 
11
11
  context 'without timeout' do
12
12
 
@@ -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(:probe) { Probe.new }
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
 
@@ -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