I would like to implement a queue capable of operating both in the FIFO mode and in the priority mode. This is a message queue, and the priority is first of all based on the message type: for example, if the messages of A type have higher priority than the messages of the B type, as a consequence all messages of A type are dequeued first, and finally the messages of B type are dequeued.
Priority mode: my idea consists of using multiple queues, one for each type of message; in this way, I can manage a priority based on the message type: just take first the messages from the queue at a higher priority and progressively from lower priority queues.
FIFO mode: how to handle FIFO mode using multiple queues? In other words, the user does not see multiple queues, but it uses the queue as if it were a single queue, so that the messages leave the queue in the order they arrive when the priority mode is disabled. In order to achieve this second goal I have thought to use a further queue to manage the order of arrival of the types of messages: let me explain better with the following code snippet.
int NUMBER_OF_MESSAGE_TYPES = 4;
int CAPACITY = 50;
Queue[] internalQueues = new Queue[NUMBER_OF_MESSAGE_TYPES];
Queue<int> queueIndexes = new Queue<int>(CAPACITY);
void Enqueue(object message)
{
int index = ... // the destination queue (ie its index) is chosen according to the type of message.
internalQueues[index].Enqueue(message);
queueIndexes.Enqueue(index);
}
object Dequeue()
{
if (fifo_mode_enabled)
{
// What is the next type that has been enqueued?
int index = queueIndexes.Dequeue();
return internalQueues[index].Dequeue();
}
if (priority_mode_enabled)
{
for(int i=0; i < NUMBER_OF_MESSAGE_TYPES; i++)
{
int currentQueueIndex = i;
if (!internalQueues[currentQueueIndex].IsEmpty())
{
object result = internalQueues[currentQueueIndex].Dequeue();
// The following statement is fundamental to a subsequent switching
// from priority mode to FIFO mode: the messages that have not been
// dequeued (since they had lower priority) remain in the order in
// which they were queued.
queueIndexes.RemoveFirstOccurrence(currentQueueIndex);
return result;
}
}
}
}
What do you think about this idea?
Are there better or more simple implementations?