Skip to content

Commit d147670

Browse files
author
Matthew Sackman
committed
merging bug 21468 into default
2 parents 1b12580 + aee5d41 commit d147670

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

projects/client/RabbitMQ.Client/src/util/SharedQueue.cs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161

6262
namespace RabbitMQ.Util {
6363
///<summary>A thread-safe shared queue implementation.</summary>
64-
public class SharedQueue {
64+
public class SharedQueue : IEnumerable {
6565
///<summary>The shared queue.</summary>
6666
///<remarks>
6767
///Subclasses must ensure appropriate locking discipline when
@@ -220,5 +220,55 @@ public bool Dequeue(int millisecondsTimeout, out object result) {
220220
return true;
221221
}
222222
}
223+
224+
///<summary>Implementation of the IEnumerable interface, for
225+
///permitting SharedQueue to be used in foreach
226+
///loops.</summary>
227+
IEnumerator IEnumerable.GetEnumerator() {
228+
return new SharedQueueEnumerator(this);
229+
}
230+
223231
}
232+
233+
///<summary>Implementation of the IEnumerator interface, for
234+
///permitting SharedQueue to be used in foreach loops.</summary>
235+
public class SharedQueueEnumerator : IEnumerator {
236+
237+
protected SharedQueue m_queue;
238+
protected object m_current;
239+
240+
///<summary>Construct an enumerator for the given
241+
///SharedQueue.</summary>
242+
public SharedQueueEnumerator(SharedQueue queue) {
243+
m_queue = queue;
244+
}
245+
246+
object IEnumerator.Current {
247+
get {
248+
if (m_current == null) {
249+
throw new InvalidOperationException();
250+
}
251+
return m_current;
252+
}
253+
}
254+
255+
bool IEnumerator.MoveNext() {
256+
try {
257+
m_current = m_queue.Dequeue();
258+
return true;
259+
} catch (EndOfStreamException) {
260+
m_current = null;
261+
return false;
262+
}
263+
}
264+
265+
///<summary>Reset()ting a SharedQueue doesn't make sense, so
266+
///this method always throws
267+
///InvalidOperationException.</summary>
268+
void IEnumerator.Reset() {
269+
throw new InvalidOperationException("SharedQueue.Reset() does not make sense");
270+
}
271+
272+
}
273+
224274
}

projects/client/Unit/src/unit/TestSharedQueue.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ public class TestSharedQueue
7272

7373
public delegate void Thunk();
7474

75+
//wrapper to work around C#'s lack of local volatiles
76+
public class VolatileInt {
77+
public volatile int v = 0;
78+
}
79+
7580
public class DelayedEnqueuer
7681
{
7782
public SharedQueue m_q;
@@ -342,6 +347,30 @@ public void TestCloseWhenWaiting()
342347
q.Close();
343348
t.Join();
344349
}
350+
351+
[Test]
352+
public void TestEnumerator()
353+
{
354+
SharedQueue q = new SharedQueue();
355+
VolatileInt c1 = new VolatileInt();
356+
VolatileInt c2 = new VolatileInt();
357+
Thread t1 = new Thread(delegate() {
358+
foreach (int v in q) c1.v+=v;
359+
});
360+
Thread t2 = new Thread(delegate() {
361+
foreach (int v in q) c2.v+=v;
362+
});
363+
t1.Start();
364+
t2.Start();
365+
q.Enqueue(1);
366+
q.Enqueue(2);
367+
q.Enqueue(3);
368+
q.Close();
369+
t1.Join();
370+
t2.Join();
371+
Assert.AreEqual(6, c1.v + c2.v);
372+
}
373+
345374
}
346375

347-
}
376+
}

0 commit comments

Comments
 (0)