Skip to content

Commit c6f3f1f

Browse files
authored
[message] disallow SetPriority() on enqueued messages in PriorityQueue (openthread#11624)
This commit modifies `Message::SetPriority()` to prevent changing a message's priority after it has been enqueued in a `PriorityQueue`. Attempting to do so will now return `kErrorInvalidState`. The functionality for altering the priority of an already-enqueued message is not currently used or required. Should this behavior become necessary in the future, the recommended approach is to explicitly dequeue the message first, then change its priority, and finally re-add it to the queue. This makes the intended behavior clearer and more explicit within the code. This commit also updates the `test_priority_queue` unit test to reflect this change.
1 parent 7617b60 commit c6f3f1f

3 files changed

Lines changed: 17 additions & 95 deletions

File tree

src/core/common/message.cpp

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -328,31 +328,17 @@ bool Message::IsMleCommand(Mle::Command aMleCommand) const
328328

329329
Error Message::SetPriority(Priority aPriority)
330330
{
331-
Error error = kErrorNone;
332-
uint8_t priority = static_cast<uint8_t>(aPriority);
333-
PriorityQueue *priorityQueue;
331+
Error error = kErrorNone;
332+
uint8_t priority = static_cast<uint8_t>(aPriority);
334333

335334
static_assert(kNumPriorities <= 4, "`Metadata::mPriority` as a 2-bit field cannot fit all `Priority` values");
336335

337336
VerifyOrExit(priority < kNumPriorities, error = kErrorInvalidArgs);
338337

339-
VerifyOrExit(IsInAQueue(), GetMetadata().mPriority = priority);
340-
VerifyOrExit(GetMetadata().mPriority != priority);
341-
342-
priorityQueue = GetPriorityQueue();
343-
344-
if (priorityQueue != nullptr)
345-
{
346-
priorityQueue->Dequeue(*this);
347-
}
338+
VerifyOrExit(!IsInAPriorityQueue(), error = kErrorInvalidState);
348339

349340
GetMetadata().mPriority = priority;
350341

351-
if (priorityQueue != nullptr)
352-
{
353-
priorityQueue->Enqueue(*this);
354-
}
355-
356342
exit:
357343
return error;
358344
}
@@ -869,7 +855,7 @@ void Message::SetMessageQueue(MessageQueue *aMessageQueue)
869855
void Message::SetPriorityQueue(PriorityQueue *aPriorityQueue)
870856
{
871857
GetMetadata().mQueue = aPriorityQueue;
872-
GetMetadata().mInPriorityQ = true;
858+
GetMetadata().mInPriorityQ = aPriorityQueue != nullptr;
873859
}
874860

875861
//---------------------------------------------------------------------------------------------------------------------

src/core/common/message.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,13 +633,15 @@ class Message : public otMessage, public Buffer, public GetProvider<Message>
633633

634634
/**
635635
* Sets the messages priority.
636-
* If the message is already queued in a priority queue, changing the priority ensures to
637-
* update the message in the associated queue.
636+
*
637+
* If the message is already enqueued in a priority queue, the priority cannot be changed and `kErrorInvalidState`
638+
* is returned.
638639
*
639640
* @param[in] aPriority The message priority level.
640641
*
641642
* @retval kErrorNone Successfully set the priority for the message.
642643
* @retval kErrorInvalidArgs Priority level is not invalid.
644+
* @retval kErrorInvalidState Message is already queued in a priority queue.
643645
*/
644646
Error SetPriority(Priority aPriority);
645647

@@ -1569,6 +1571,8 @@ class Message : public otMessage, public Buffer, public GetProvider<Message>
15691571
}
15701572

15711573
bool IsInAQueue(void) const { return (GetMetadata().mQueue != nullptr); }
1574+
bool IsInAPriorityQueue(void) const { return GetMetadata().mInPriorityQ; }
1575+
15721576
void SetMessageQueue(MessageQueue *aMessageQueue);
15731577
void SetPriorityQueue(PriorityQueue *aPriorityQueue);
15741578

tests/unit/test_priority_queue.cpp

Lines changed: 7 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -135,44 +135,11 @@ void VerifyPriorityQueueContent(PriorityQueue &aPriorityQueue, int aExpectedLeng
135135
VerifyOrQuit(message == nullptr, "`for` loop iteration resulted in fewer entries than expected");
136136
}
137137

138-
// This function verifies the content of the message queue to match the passed in messages
139-
void VerifyMsgQueueContent(MessageQueue &aMessageQueue, int aExpectedLength, ...)
140-
{
141-
va_list args;
142-
Message *message;
143-
Message *msgArg;
144-
145-
va_start(args, aExpectedLength);
146-
147-
if (aExpectedLength == 0)
148-
{
149-
message = aMessageQueue.GetHead();
150-
VerifyOrQuit(message == nullptr, "is not empty when expected len is zero.");
151-
}
152-
else
153-
{
154-
for (message = aMessageQueue.GetHead(); message != nullptr; message = message->GetNext())
155-
{
156-
VerifyOrQuit(aExpectedLength != 0, "contains more entries than expected");
157-
158-
msgArg = va_arg(args, Message *);
159-
VerifyOrQuit(msgArg == message, "content does not match what is expected.");
160-
161-
aExpectedLength--;
162-
}
163-
164-
VerifyOrQuit(aExpectedLength == 0, "contains less entries than expected");
165-
}
166-
167-
va_end(args);
168-
}
169-
170138
void TestPriorityQueue(void)
171139
{
172140
Instance *instance;
173141
MessagePool *messagePool;
174142
PriorityQueue queue;
175-
MessageQueue messageQueue;
176143
Message *msgNet[kNumTestMessages];
177144
Message *msgHigh[kNumTestMessages];
178145
Message *msgNor[kNumTestMessages];
@@ -264,62 +231,27 @@ void TestPriorityQueue(void)
264231
queue.Dequeue(*msgHigh[3]);
265232
VerifyPriorityQueueContent(queue, 0);
266233

267-
// Change the priority of an already queued message and check the order change in the queue.
234+
// Validate that priority of an already queued message in a priority queue cannot change
268235
queue.Enqueue(*msgNor[0]);
269236
VerifyPriorityQueueContent(queue, 1, msgNor[0]);
270237
queue.Enqueue(*msgHigh[0]);
271238
VerifyPriorityQueueContent(queue, 2, msgHigh[0], msgNor[0]);
272239
queue.Enqueue(*msgLow[0]);
273240
VerifyPriorityQueueContent(queue, 3, msgHigh[0], msgNor[0], msgLow[0]);
274241

275-
SuccessOrQuit(msgNor[0]->SetPriority(Message::kPriorityNet));
276-
VerifyPriorityQueueContent(queue, 3, msgNor[0], msgHigh[0], msgLow[0]);
277-
SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityLow));
278-
VerifyPriorityQueueContent(queue, 3, msgNor[0], msgHigh[0], msgLow[0]);
279-
SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityNormal));
280-
VerifyPriorityQueueContent(queue, 3, msgNor[0], msgHigh[0], msgLow[0]);
281-
SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityHigh));
282-
VerifyPriorityQueueContent(queue, 3, msgNor[0], msgHigh[0], msgLow[0]);
283-
SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityNet));
284-
VerifyPriorityQueueContent(queue, 3, msgNor[0], msgLow[0], msgHigh[0]);
285-
SuccessOrQuit(msgNor[0]->SetPriority(Message::kPriorityNormal));
286-
SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityLow));
242+
VerifyOrQuit(msgNor[0]->SetPriority(Message::kPriorityNet) == kErrorInvalidState);
243+
VerifyOrQuit(msgLow[0]->SetPriority(Message::kPriorityLow) == kErrorInvalidState);
244+
VerifyOrQuit(msgLow[0]->SetPriority(Message::kPriorityNormal) == kErrorInvalidState);
245+
VerifyOrQuit(msgHigh[0]->SetPriority(Message::kPriorityNormal) == kErrorInvalidState);
287246
VerifyPriorityQueueContent(queue, 3, msgHigh[0], msgNor[0], msgLow[0]);
288247

289-
messageQueue.Enqueue(*msgNor[1]);
290-
messageQueue.Enqueue(*msgHigh[1]);
291-
messageQueue.Enqueue(*msgNet[1]);
292-
VerifyMsgQueueContent(messageQueue, 3, msgNor[1], msgHigh[1], msgNet[1]);
293-
294-
// Change priority of message and check for not in messageQueue.
295-
SuccessOrQuit(msgNor[1]->SetPriority(Message::kPriorityNet));
296-
VerifyMsgQueueContent(messageQueue, 3, msgNor[1], msgHigh[1], msgNet[1]);
297-
298-
SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityHigh));
299-
VerifyPriorityQueueContent(queue, 3, msgHigh[0], msgLow[0], msgNor[0]);
300-
VerifyMsgQueueContent(messageQueue, 3, msgNor[1], msgHigh[1], msgNet[1]);
301-
302-
// Remove messages from the two queues
248+
// Remove messages from the queue
303249
queue.Dequeue(*msgHigh[0]);
304-
VerifyPriorityQueueContent(queue, 2, msgLow[0], msgNor[0]);
305-
VerifyMsgQueueContent(messageQueue, 3, msgNor[1], msgHigh[1], msgNet[1]);
306-
307-
messageQueue.Dequeue(*msgNet[1]);
308-
VerifyPriorityQueueContent(queue, 2, msgLow[0], msgNor[0]);
309-
VerifyMsgQueueContent(messageQueue, 2, msgNor[1], msgHigh[1]);
310-
311-
messageQueue.Dequeue(*msgHigh[1]);
312-
VerifyPriorityQueueContent(queue, 2, msgLow[0], msgNor[0]);
313-
VerifyMsgQueueContent(messageQueue, 1, msgNor[1]);
314-
250+
VerifyPriorityQueueContent(queue, 2, msgNor[0], msgLow[0]);
315251
queue.Dequeue(*msgLow[0]);
316252
VerifyPriorityQueueContent(queue, 1, msgNor[0]);
317-
VerifyMsgQueueContent(messageQueue, 1, msgNor[1]);
318-
319253
queue.Dequeue(*msgNor[0]);
320254
VerifyPriorityQueueContent(queue, 0);
321-
messageQueue.Dequeue(*msgNor[1]);
322-
VerifyMsgQueueContent(messageQueue, 0);
323255

324256
for (Message *message : msgNor)
325257
{

0 commit comments

Comments
 (0)