@@ -71,7 +71,19 @@ public class WorkPool<K, W> {
7171
7272 // This is like a LinkedBlockingQueue of limited length except you can turn the limit
7373 // on and off. And it only has the methods we need.
74- // TODO synchronised how?
74+ //
75+ // This class is partly synchronised because:
76+ //
77+ // a) we cannot make put(T) synchronised as it may block indefinitely. Therefore we
78+ // only lock before modifying the list.
79+ // b) we don't want to make setLimited() synchronised as it is called frequently by
80+ // the channel.
81+ // c) anyway the issue with setLimited() is not that it be synchronised itself but
82+ // that calls to it should alternate between false and true. We assert this, but
83+ // it should not be able to go wrong because the RPC calls in AMQChannel and
84+ // ChannelN are all protected by the _channelMutex; we can't have more than one
85+ // outstanding RPC or finish the same RPC twice.
86+
7587 private static class WorkQueue <T > {
7688 private Semaphore semaphore ;
7789 private LinkedList <T > list ;
@@ -90,10 +102,12 @@ public void put(T t) throws InterruptedException {
90102 assert !semaphore .hasQueuedThreads ();
91103 semaphore .acquire ();
92104 }
93- list .add (t );
105+ synchronized (this ) {
106+ list .add (t );
107+ }
94108 }
95109
96- public T poll () {
110+ public synchronized T poll () {
97111 T res = list .poll ();
98112
99113 if (list .size () <= maxLengthWhenLimited && semaphore .hasQueuedThreads ()) {
@@ -104,6 +118,7 @@ public T poll() {
104118 }
105119
106120 public void setLimited (boolean limited ) {
121+ assert this .limited != limited ;
107122 this .limited = limited ;
108123 if (!limited && semaphore .hasQueuedThreads ()) {
109124 semaphore .release ();
0 commit comments