nobody wrote on Wednesday, December 20, 2006:
Is there a way to peek a queue, i.e. not remove the message from the queue, just see if it is there ?
nobody wrote on Wednesday, December 20, 2006:
Is there a way to peek a queue, i.e. not remove the message from the queue, just see if it is there ?
nobody wrote on Wednesday, December 20, 2006:
uxQueueMessagesWaiting() will tell you if there is anything on the queue but not let you actually look at what is on the queue. Is this what you want?
nobody wrote on Wednesday, December 20, 2006:
Thank you, but I need to look at what is on the queue.
nobody wrote on Wednesday, December 20, 2006:
I would suggest the following:
signed portBASE_TYPE xQueuePeak( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait)
{
signed portBASE_TYPE xReturn;
signed portCHAR *pMsg;
xTimeOutType xTimeOut;
//Make sure other tasks do not access the queue. */
vTaskSuspendAll();
/* Capture the current time status for future reference. */
vTaskSetTimeOutState( &xTimeOut );
/* Make sure interrupts do not access the queue. */
prvLockQueue( pxQueue );
do
{
/* If there are no messages in the queue we may have to block. */
if( prvIsQueueEmpty( pxQueue ) )
{
/* There are no messages in the queue, do we want to block or just
leave with nothing? */
if( xTicksToWait > ( portTickType ) 0 )
{
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
taskENTER_CRITICAL();
{
prvUnlockQueue( pxQueue );
if( !xTaskResumeAll() )
{
taskYIELD();
}
vTaskSuspendAll();
prvLockQueue( pxQueue );
}
taskEXIT_CRITICAL();
}
}
taskENTER_CRITICAL();
{
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
{
pMsg=pxQueue->pcReadFrom;
pMsg += pxQueue->uxItemSize;
if( pMsg >= pxQueue->pcTail )
{
pMsg = pxQueue->pcHead;
}
memcpy( ( void * ) pvBuffer, ( void * ) pMsg, ( unsigned ) pxQueue->uxItemSize );
/* Increment the lock count so prvUnlockQueue knows to check for
tasks waiting for space to become available on the queue. */
//++( pxQueue->xRxLock );
xReturn = pdPASS;
}
else
{
xReturn = errQUEUE_EMPTY;
}
}
taskEXIT_CRITICAL();
if( xReturn == errQUEUE_EMPTY )
{
if( xTicksToWait > 0 )
{
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
{
xReturn = queueERRONEOUS_UNBLOCK;
}
}
}
} while( xReturn == queueERRONEOUS_UNBLOCK );
/* We no longer require exclusive access to the queue. */
prvUnlockQueue( pxQueue );
xTaskResumeAll();
return xReturn;
}
nobody wrote on Wednesday, December 20, 2006:
Add this to queue.c
signed portBASE_TYPE xQueuePeek( xQueueHandle pxQueue, void *pvBuffer )
{
signed portBASE_TYPE xReturn;
xTimeOutType xTimeOut;
unsigned char *pcReadFrom;
taskENTER_CRITICAL();
{
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
{
pcReadFrom = pxQueue->pcReadFrom;
pcReadFrom += pxQueue->uxItemSize;
if( pcReadFrom >= pxQueue->pcTail )
{
pcReadFrom = pxQueue->pcHead;
}
memcpy( ( void * ) pvBuffer, ( void * ) pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
xReturn = pdPASS;
}
else
{
xReturn = errQUEUE_EMPTY;
}
}
taskEXIT_CRITICAL();
return xReturn;
}
imajeff wrote on Tuesday, December 26, 2006:
To the Nobody who suggested xQueuePeak(), I doubt anyone would want the “peek” function to block. The point would simply be to see what is there at the modment, or indicate that nothing is there. I suppose it would still work since you can wait 0, but still it complicates and slows down excecution, I think unnecessarily. (But could it be useful for things I didn’t think of?)
nobody wrote on Tuesday, January 09, 2007:
Just think of the case where you are waiting for a message to arrive, but don’t want to remove it from the queue as it arrives.
In that case it is useful to wait and not eat processor time polling the queue.
xterse wrote on Tuesday, May 06, 2008:
How about adding possibility to peek from interrupt routine?
I need to use it in my XON/XOFF handle.
Here is what I added that works for me.
Rgrds
if( xQueuePeekFromISR( xCrsTXDQueue, &cChar ) == pdTRUE )
{
…
}
//************************************************************************************
//
// xQueuePeekFromISR
//
// Get serial port flow control.
//
// Input: xQueueHandle pxQueue
// const void * const pvBuffer
//
// Output: signed portBASE_TYPE pdFAIL if no character
// pdPASS if character found
//
// Sets: pvBuffer value
//
//************************************************************************************
signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle pxQueue, const void * const pvBuffer )
{
signed portBASE_TYPE xReturn;
/* We cannot block from an ISR, so check there is data available. */
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
{
prvCopyPeekDataFromQueue( pxQueue, pvBuffer );
// --( pxQueue->uxMessagesWaiting ); // Don’t update number of messages in queue!
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
return xReturn;
}
//************************************************************************************
//
// prvCopyPeekDataFromQueue
//
// Get data from queue without destroying it.
//
// Input: xQUEUE * const pxQueue
// const void *pvBuffer
//
// Output: -
//
// Sets: data that pvBuffer points to
//
//************************************************************************************
static void prvCopyPeekDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
{
signed portCHAR *pcTempReadFrom;
if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
{
pcTempReadFrom = pxQueue->pcReadFrom + pxQueue->uxItemSize; // Point to new location
if( pcTempReadFrom >= pxQueue->pcTail )
{
pcTempReadFrom = pxQueue->pcHead; // Point to start of buffer
}
memcpy( ( void * ) pvBuffer, ( void * ) pcTempReadFrom, ( unsigned ) pxQueue->uxItemSize );
}
}