First steps was to use LinkedBlockingDeque to provide an iterator on PriorityLinkedList which allows forconcurrent traversals and mutations

Next step is to refactor the server-side to have the browser works on the iterator

How does a browser differ from a simple consumer?2/ the queue will deliver all messages to the browser but never removed the corresponding references3/ the queue must not deliver messages to the browser through its distribution policy

Delivering messages to browsers and to regular consumers are two different code paths that cannot occur in the same loop

When a consumer is added to the queue, the queue could check if it is a browser or not.If it is a browser, it is *not* added to the Distributor.

For now there is a single DeliverRunner for the queue (-> regular code path)We could add other Runnable for every browser with their own iterators.When the session is prompted to deliver, we must check if the consumer prompting for delivery isa browser or not.if it is a browser, a Runnable will be created with its own iterator and executed. It will deliver all ref to the browser *without removing the ref from the iterator*if it is not a browser, regular code path applies

When a consumer is removed, we check if there is a Runnable associated to it and stop it if necessarywdyt?

You always start a thread that will deliver to the client from the beggining of the queue.

When you call promptDelivery, you are supposed to resume where you left sending messages. And you are aways resuming from the beggining, what is creating order issues on the test.

You are also starting multiple senders as you receive credits. And that is duplicating sends also.

The server should send messages to the client as long as you have credits, when you are out of credits you should give up sending. Next time promptDelivery is called you should resume the process again.

That is not an exclusive problem on LargeMessages. (It's just that you run out of credits earlier with Large Messages).

You will have several problems with regular messages also if you run a test where you limit your credits.

The way the Consumer used to work was on a copy of a Queue, right?

Why don't you create some sort of QueueIterator that encapsulates the iteration?

Maybe:

class QueueIteratorImpl implements Queue
{
... you encapsulate the iteration here to the main Queue
}

On the process of resuming send, you should also check if largeMessageDeliverer != null and resume sending a largeMessage.

If you provide some sort of QueueIterator implements Queue as I said you won't need to change a line on the ServerConsumer, what would be much easier to debug.

Writing the thread the way you did may look a shortcut (less code), but this promptDelivery thing was a hard thing to tune up. (I needed some time to get my head into it). If you avoid touching it would be better for you.