xQueueGenericSend and xQueueReceive

Hi there,I met a question about the function xQueueGenericSend() and xQueueReceive().I notice that when the time is out,xQueueGenericSend() return “errQUEUE_FULL“ directly.But xQueueReceive() is different, it judged the queue is empty again.

I want to know why xQueueGenericSend() does not judged the queue is full again when the time is out just now?

Hi could you explain the sequence of events you are observing? I’m not sure I understand the situation.

I’m going to use an analogy for a second to better explain the queue. Let’s imagine the queue as a box which you can place and remove things from.

When you want to put things into the box, you would call xQueueSend. If there is space in the box, it will place the item in the box and return that it was able to put the item into the box (success). However, if the box is full and cannot fit anything else, xQueueSend has two choices. The first option is to return that the queue is full (aka errQUEUE_FULL). The second option is to wait for the box to have space. You can control how long this waits with xTicksToWait. If you set this value, it will wait up to that number of ticks for there to be space in the box. If something is removed from the box before that number of ticks, then xQueueSend places the item into the box and returns success. If it does not, it will time out as the box (aka queue) is still full.

When you take things from the box pretty much the opposite happens. If there is something in the box when you call xQueueReceive then you can take it from the box immediately and the function returns success. If there is nothing in the box however, you have the two options once again. You can either immediately return that the box is empty (aka errQUEUE_EMPTY) or you can wait for a certain time until timeout for something to be in the box.


With this background in mind, your question is rather puzzling. xQueueGenericSend shouldn’t return that the queue is full if xQueueReceive is returning empty assuming no items are placed into the queue between the calls.

Can you include some of your code so we can take a look at what’s going on?



The two screenshots above show parts of the code for xQueueGenericSend and xQueueReceive respectively. My question is: when sending to the queue, why does it directly return “queue is full” after determining a timeout, without checking again whether the current queue is full? However, when receiving from the queue, after determining a timeout, it checks again whether the queue is empty. The handling of enqueue and dequeue is inconsistent. Is there any special consideration for this?

The two screenshots above show parts of the code for xQueueGenericSend and xQueueReceive respectively. My question is: when sending to the queue, why does it directly return “queue is full” after determining a timeout, without checking again whether the current queue is full? However, when receiving from the queue, after determining a timeout, it checks again whether the queue is empty. The handling of enqueue and dequeue is inconsistent. Is there any special consideration for this?

Yes,here are two screenshots of my question.

I was able to find the commit originating the comment and this commit originating the behaviorbut it doesn’t shed light on why this difference was introduced. I have wondered this myself before but always seem to bottom out here.

The only reasoning is that this was added

to catch the extreme case of data being placed into a queue between a task timing out and leaving the xQueueGenericReceive() function.

I can understand that when in an extreme situation: in the xQueueReceive function, after a judgment timeout, if an interrupt or a high-priority task re-sends a message to the queue, then re-checking whether it is empty does not require losing this message. However, xQueueGenericSend can also encounter such an extreme situation. When the queue is full and times out, a certain interrupt or high-priority task happens to read a message, causing the queue to have spare space. At this point, in my understanding, before returning that the queue is full, it should be rechecked whether it is full.

Or we should remove this logic of re-checking from the receive path too as timeout has already happened.

yes, I think so.I’m just not sure if there are any special scenario considerations in this, which is why it was designed this way. If not, I think sending messages and receiving messages should be completely symmetrical and reverse operations. Either check the queue condition once after the timeout, or return the timeout result directly without checking either after the timeout.

1 Like

Of course, by the way, does this difference between sending and receiving messages have almost no significant impact on practical applications

I tend to agree with that argument and would also like to commend you for unearthing this asymmetry, thanks!

I also agree with symmetry in operation. Would you like to raise a PR removing the post-timeout check?

Sorry, I don’t know.I’m just a little confused about this asymmetry, and i have never raise a PR or something others, so I don’t know what i should to do.

My guess s the asymmetry came about as they likely started the same, but the missing the late (after timeout) becoming ready was bothersome to someone on one path, so it was changed there, but not the other.

The difference can’t be called an error, as it depends on a race condition.