[message-queue] enable adding a message to head of queue (#2246)

This commit updates the `MessageQueue` implementation to allow
messages to be added to head/front of the queue. It adds new methods
to the `MessageQueue` class and a corresponding one in public
OpenThread APIs (`otMessageQueueEnqueueAtHead()`). This commit also
updates the `test_message_queue` unit test to add cases/scenarios for
testing the new methods and public APIs.
This commit is contained in:
Abtin Keshavarzian
2017-10-11 15:15:53 -07:00
committed by Jonathan Hui
parent 95f744fbb4
commit 2578a7bf8c
5 changed files with 109 additions and 18 deletions
+12 -1
View File
@@ -238,7 +238,6 @@ typedef struct
} otMessageQueue;
/**
*
* Initialize the message queue.
*
* This function MUST be called once and only once for a `otMessageQueue` instance before any other `otMessageQueue`
@@ -262,6 +261,18 @@ void otMessageQueueInit(otMessageQueue *aQueue);
*/
otError otMessageQueueEnqueue(otMessageQueue *aQueue, otMessage *aMessage);
/**
* This function adds a message at the head/front of the given message queue.
*
* @param[in] aQueue A pointer to the message queue.
* @param[in] aMessage The message to add.
*
* @retval OT_ERROR_NONE Successfully added the message to the queue.
* @retval OT_ERROR_ALREADY The message is already enqueued in a queue.
*
*/
otError otMessageQueueEnqueueAtHead(otMessageQueue *aQueue, otMessage *aMessage);
/**
* This function removes a message from the given message queue.
*
+7
View File
@@ -123,6 +123,13 @@ otError otMessageQueueEnqueue(otMessageQueue *aQueue, otMessage *aMessage)
return queue->Enqueue(*message);
}
otError otMessageQueueEnqueueAtHead(otMessageQueue *aQueue, otMessage *aMessage)
{
Message *message = static_cast<Message *>(aMessage);
MessageQueue *queue = static_cast<MessageQueue *>(aQueue);
return queue->Enqueue(*message, MessageQueue::kQueuePositionHead);
}
otError otMessageQueueDequeue(otMessageQueue *aQueue, otMessage *aMessage)
{
Message *message = static_cast<Message *>(aMessage);
+13 -8
View File
@@ -811,29 +811,32 @@ MessageQueue::MessageQueue(void)
SetTail(NULL);
}
void MessageQueue::AddToList(uint8_t aList, Message &aMessage)
void MessageQueue::AddToList(uint8_t aList, Message &aMessage, QueuePosition aPosition)
{
Message *head;
assert((aMessage.Next(aList) == NULL) && (aMessage.Prev(aList) == NULL));
if (GetTail() == NULL)
{
aMessage.Next(aList) = &aMessage;
aMessage.Prev(aList) = &aMessage;
SetTail(&aMessage);
}
else
{
head = GetTail()->Next(aList);
Message *head = GetTail()->Next(aList);
aMessage.Next(aList) = head;
aMessage.Prev(aList) = GetTail();
head->Prev(aList) = &aMessage;
GetTail()->Next(aList) = &aMessage;
}
SetTail(&aMessage);
if (aPosition == kQueuePositionTail)
{
SetTail(&aMessage);
}
}
}
void MessageQueue::RemoveFromList(uint8_t aList, Message &aMessage)
@@ -862,7 +865,7 @@ Message *MessageQueue::GetHead(void) const
return (GetTail() == NULL) ? NULL : GetTail()->Next(MessageInfo::kListInterface);
}
otError MessageQueue::Enqueue(Message &aMessage)
otError MessageQueue::Enqueue(Message &aMessage, QueuePosition aPosition)
{
otError error = OT_ERROR_NONE;
@@ -870,7 +873,9 @@ otError MessageQueue::Enqueue(Message &aMessage)
aMessage.SetMessageQueue(this);
AddToList(MessageInfo::kListInterface, aMessage);
AddToList(MessageInfo::kListInterface, aMessage, aPosition);
// Any new message is always added to the end of the `AllMessageQueue` list.
aMessage.GetMessagePool()->GetAllMessagesQueue()->AddToList(MessageInfo::kListAll, aMessage);
exit:
+37 -3
View File
@@ -810,6 +810,18 @@ class MessageQueue : public otMessageQueue
friend class PriorityQueue;
public:
/**
* This enumeration represents a position (head or tail) in the queue. This is used to specify where a new message
* should be added in the queue.
*
*/
enum QueuePosition
{
kQueuePositionHead, ///< Indicates the head (front) of the list.
kQueuePositionTail, ///< Indicates the tail (end) of the list.
};
/**
* This constructor initializes the message queue.
*
@@ -833,7 +845,19 @@ public:
* @retval OT_ERROR_ALREADY The message is already enqueued in a list.
*
*/
otError Enqueue(Message &aMessage);
otError Enqueue(Message &aMessage) { return Enqueue(aMessage, kQueuePositionTail); }
/**
* This method adds a message at a given position (head/tail) of the list.
*
* @param[in] aMessage The message to add.
* @param[in] aPosition The position (head or tail) where to add the message.
*
* @retval OT_ERROR_NONE Successfully added the message to the list.
* @retval OT_ERROR_ALREADY The message is already enqueued in a list.
*
*/
otError Enqueue(Message &aMessage, QueuePosition aPosition);
/**
* This method removes a message from the list.
@@ -874,13 +898,23 @@ private:
void SetTail(Message *aMessage) { mData = aMessage; }
/**
* This method adds a message to a list.
* This method adds a message to the end of the list.
*
* @param[in] aListId The list to add @p aMessage to.
* @param[in] aMessage The message to add to @p aListId.
*
*/
void AddToList(uint8_t aListId, Message &aMessage);
void AddToList(uint8_t aListId, Message &aMessage) { AddToList(aListId, aMessage, kQueuePositionTail); }
/**
* This method adds a message at a give position (head or tail) of the list.
*
* @param[in] aListId The list to add @p aMessage to.
* @param[in] aMessage The message to add to @p aListId.
* @param[in] aPosition The position where to add the message.
*
*/
void AddToList(uint8_t aListId, Message &aMessage, QueuePosition aPosition);
/**
* This method removes a message from a list.
+40 -6
View File
@@ -103,6 +103,13 @@ void TestMessageQueue(void)
SuccessOrQuit(messageQueue.Dequeue(*msg[0]), "MessageQueue::Dequeue() failed.\n");
VerifyMessageQueueContent(messageQueue, 0);
// Enqueue 1 message at head and remove it
SuccessOrQuit(messageQueue.Enqueue(*msg[0], ot::MessageQueue::kQueuePositionHead),
"MessageQueue::Enqueue() failed.\n");
VerifyMessageQueueContent(messageQueue, 1, msg[0]);
SuccessOrQuit(messageQueue.Dequeue(*msg[0]), "MessageQueue::Dequeue() failed.\n");
VerifyMessageQueueContent(messageQueue, 0);
// Enqueue 5 messages
SuccessOrQuit(messageQueue.Enqueue(*msg[0]), "MessageQueue::Enqueue() failed.\n");
VerifyMessageQueueContent(messageQueue, 1, msg[0]);
@@ -131,18 +138,45 @@ void TestMessageQueue(void)
SuccessOrQuit(messageQueue.Dequeue(*msg[4]), "MessageQueue::Dequeue() failed.\n");
VerifyMessageQueueContent(messageQueue, 2, msg[1], msg[2]);
// Add after removes
// Add after remove
SuccessOrQuit(messageQueue.Enqueue(*msg[0]), "MessageQueue::Enqueue() failed.\n");
VerifyMessageQueueContent(messageQueue, 3, msg[1], msg[2], msg[0]);
SuccessOrQuit(messageQueue.Enqueue(*msg[3]), "MessageQueue::Enqueue() failed.\n");
VerifyMessageQueueContent(messageQueue, 4, msg[1], msg[2], msg[0], msg[3]);
// Remove all messages
// Remove from middle
SuccessOrQuit(messageQueue.Dequeue(*msg[2]), "MessageQueue::Dequeue() failed.\n");
VerifyMessageQueueContent(messageQueue, 3, msg[1], msg[0], msg[3]);
// Add to head
SuccessOrQuit(messageQueue.Enqueue(*msg[2], ot::MessageQueue::kQueuePositionHead),
"MessageQueue::Enqueue() failed.\n");
VerifyMessageQueueContent(messageQueue, 4, msg[2], msg[1], msg[0], msg[3]);
// Remove from head
SuccessOrQuit(messageQueue.Dequeue(*msg[2]), "MessageQueue::Dequeue() failed.\n");
VerifyMessageQueueContent(messageQueue, 3, msg[1], msg[0], msg[3]);
// Remove from head
SuccessOrQuit(messageQueue.Dequeue(*msg[1]), "MessageQueue::Dequeue() failed.\n");
VerifyMessageQueueContent(messageQueue, 2, msg[0], msg[3]);
// Add to head
SuccessOrQuit(messageQueue.Enqueue(*msg[1], ot::MessageQueue::kQueuePositionHead),
"MessageQueue::Enqueue() failed.\n");
VerifyMessageQueueContent(messageQueue, 3, msg[1], msg[0], msg[3]);
// Add to tail
SuccessOrQuit(messageQueue.Enqueue(*msg[2], ot::MessageQueue::kQueuePositionTail),
"MessageQueue::Enqueue() failed.\n");
VerifyMessageQueueContent(messageQueue, 4, msg[1], msg[0], msg[3], msg[2]);
// Remove all messages.
SuccessOrQuit(messageQueue.Dequeue(*msg[3]), "MessageQueue::Dequeue() failed.\n");
VerifyMessageQueueContent(messageQueue, 3, msg[1], msg[0], msg[2]);
SuccessOrQuit(messageQueue.Dequeue(*msg[1]), "MessageQueue::Dequeue() failed.\n");
VerifyMessageQueueContent(messageQueue, 2, msg[0], msg[2]);
SuccessOrQuit(messageQueue.Dequeue(*msg[2]), "MessageQueue::Dequeue() failed.\n");
VerifyMessageQueueContent(messageQueue, 1, msg[0]);
SuccessOrQuit(messageQueue.Dequeue(*msg[0]), "MessageQueue::Dequeue() failed.\n");
VerifyMessageQueueContent(messageQueue, 0);
@@ -222,14 +256,14 @@ void TestMessageQueueOtApis(void)
VerifyMessageQueueContentUsingOtApi(&queue, 1, msg[0]);
SuccessOrQuit(otMessageQueueEnqueue(&queue, msg[1]), "Failed to enqueue a message to otMessageQueue.\n");
VerifyMessageQueueContentUsingOtApi(&queue, 2, msg[0], msg[1]);
SuccessOrQuit(otMessageQueueEnqueue(&queue, msg[2]), "Failed to enqueue a message to otMessageQueue.\n");
VerifyMessageQueueContentUsingOtApi(&queue, 3, msg[0], msg[1], msg[2]);
SuccessOrQuit(otMessageQueueEnqueueAtHead(&queue, msg[2]), "Failed to enqueue a message to otMessageQueue.\n");
VerifyMessageQueueContentUsingOtApi(&queue, 3, msg[2], msg[0], msg[1]);
SuccessOrQuit(otMessageQueueEnqueue(&queue, msg[3]), "Failed to enqueue a message to otMessageQueue.\n");
VerifyMessageQueueContentUsingOtApi(&queue, 4, msg[0], msg[1], msg[2], msg[3]);
VerifyMessageQueueContentUsingOtApi(&queue, 4, msg[2], msg[0], msg[1], msg[3]);
// Remove elements and check the content
SuccessOrQuit(otMessageQueueDequeue(&queue, msg[1]), "Failed to dequeue a message from otMessageQueue.\n");
VerifyMessageQueueContentUsingOtApi(&queue, 3, msg[0], msg[2], msg[3]);
VerifyMessageQueueContentUsingOtApi(&queue, 3, msg[2], msg[0], msg[3]);
SuccessOrQuit(otMessageQueueDequeue(&queue, msg[0]), "Failed to dequeue a message from otMessageQueue.\n");
VerifyMessageQueueContentUsingOtApi(&queue, 2, msg[2], msg[3]);
SuccessOrQuit(otMessageQueueDequeue(&queue, msg[3]), "Failed to dequeue a message from otMessageQueue.\n");