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.
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