[message] change queues to use non-circular linked list (#11630)

This commit updates the `MessageQueue` and `PriorityQueue`
implementations to use non-circular doubly linked lists instead of
the previous circular ones. Using a non-circular list requires the
queue to track the head element, but it simplifies common operations
like getting the head and iterating over the messages.

Particularly, `Message::GetNext()` now simply returns the `mNext`
pointer. Previously, `Message` had to store a pointer to its `mQueue`
within its `Metadata` to identify the tail of the queue and stop the
iteration correctly.

This commit also updates the unit tests. In particular,
`test_priority_queue` is significantly enhanced to cover many
scenarios, such as multiple messages with the same priority, and
messages with different priorities being added and removed in various
orders.
This commit is contained in:
Abtin Keshavarzian
2025-06-25 13:03:43 -07:00
committed by GitHub
parent 5d1d380012
commit c55098af5e
7 changed files with 694 additions and 268 deletions
+40 -2
View File
@@ -133,6 +133,46 @@ void TestMessageQueue(void)
messageQueue.Dequeue(*messages[0]);
VerifyMessageQueueContent(messageQueue, 0);
// Enqueue 2 messages and remove them in the same order added.
messageQueue.Enqueue(*messages[0]);
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
messageQueue.Enqueue(*messages[1]);
VerifyMessageQueueContent(messageQueue, 2, messages[0], messages[1]);
messageQueue.Dequeue(*messages[0]);
VerifyMessageQueueContent(messageQueue, 1, messages[1]);
messageQueue.Dequeue(*messages[1]);
VerifyMessageQueueContent(messageQueue, 0);
// Enqueue 2 messages and remove them in reverse order added.
messageQueue.Enqueue(*messages[0]);
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
messageQueue.Enqueue(*messages[1]);
VerifyMessageQueueContent(messageQueue, 2, messages[0], messages[1]);
messageQueue.Dequeue(*messages[1]);
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
messageQueue.Dequeue(*messages[0]);
VerifyMessageQueueContent(messageQueue, 0);
// Enqueue 2 messages at the head and remove them in the same order added.
messageQueue.Enqueue(*messages[0], MessageQueue::kQueuePositionHead);
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
messageQueue.Enqueue(*messages[1], MessageQueue::kQueuePositionHead);
VerifyMessageQueueContent(messageQueue, 2, messages[1], messages[0]);
messageQueue.Dequeue(*messages[0]);
VerifyMessageQueueContent(messageQueue, 1, messages[1]);
messageQueue.Dequeue(*messages[1]);
VerifyMessageQueueContent(messageQueue, 0);
// Enqueue 2 messages at the head and remove them in the reverse order added.
messageQueue.Enqueue(*messages[0], MessageQueue::kQueuePositionHead);
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
messageQueue.Enqueue(*messages[1], MessageQueue::kQueuePositionHead);
VerifyMessageQueueContent(messageQueue, 2, messages[1], messages[0]);
messageQueue.Dequeue(*messages[1]);
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
messageQueue.Dequeue(*messages[0]);
VerifyMessageQueueContent(messageQueue, 0);
// Enqueue 5 messages
messageQueue.Enqueue(*messages[0]);
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
@@ -333,8 +373,6 @@ void TestMessageQueueOtApis(void)
message = otMessageQueueGetNext(&queue2, messages[0]);
VerifyOrQuit(message == messages[1], "otMessageQueueGetNext() failed");
message = otMessageQueueGetNext(&queue, messages[0]);
VerifyOrQuit(message == nullptr, "otMessageQueueGetNext() did not return nullptr for message not in the queue.");
// Remove all element and make sure queue is empty
otMessageQueueDequeue(&queue, messages[2]);