Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Sending different objects to a queue

Posted by jinx on May 28, 2010
I am looking for the best way to pass different objects into the same queue for my lcd task. I am using C.

As an example, I am faced with sending different objects such as strings, bmps, buttons, etc to an lcdTask's queue.

Is there an elegant and efficient way to do this, or is this a no-no in practice?

Here are my thoughts on one approach for doing this:

I was thinking of using a struct that contains

struct object
int dataType; //string, bmp, etc
void * data; //pointer to the string, bmp, etc

and then the lcd task will get the dataType from this object struct and then use that information to properly dereference the data. Is this a good way to send different datatypes to the same queue or is there a better way? The one question I have about this approach is how do the tasks putting this data into the lcdQueue find out the type of datatypes available (string, bmp, etc). If I define these datatype structs in lcd.h (where the lcd task is), then what is the best way for functions residing in other modules to find out the datatypes and how to populate them...right now, the way I was thinking to handle this is to store these datatype structs in the lcd.h file to share the datatype (string, bmp) directly. Is there a better way to do this, for example, by utilizing a public function in lcd.c that the callee residing in another module can ask for the different types of datatypes (string, bmp) available?

Thanks for your insight and help.

RE: Sending different objects to a queue

Posted by Richard Damon on May 28, 2010
Let me give a few suggestions to help here.

First, change the int dataType to and enum. This has the advantage that it clearly documents the list of types and the value to be used. Also some compilers when you switch on an enum will generate an error if there is an unhandled enum balue.

Second, change the void* to a union of pointer types. This again makes it clear what types are allowed, and also allows for an int parm (or other simple type like long or float) if some message could use that, this may not apply to your case, but in general for a multi-type message might be useful.

This would make your structure look something like this:

enum lcd_msg_type { LCD_String, LCD_Bmp };
struct lcd_message {
enum lcd_msg_type type;
union {
char* stringptr;
struct bmp* bmpptr;
} data;

(add more enum and pointers as needed)

I would also not put this definition in lcd.h, but instead provide a set of functions like lcd_string(char*) that take the various things to be sent to the lcd, and add them to the queue itself. That way there is less code to review to make sure the type and data are consistent. The definition would then just reside in lcd.c (or in lcd_impl.h if lcd.c grows too big and needs to be split, or if style guides request that all structures be defined in a header.)

RE: Sending different objects to a queue

Posted by jinx on May 28, 2010
Thanks Richard,

This is the exact information that I was looking.

I'm curious, can void pointers be utilized in addition to your suggestion to improve things further. Do you generally use void pointers in your work and if so, do you have suggestions where they are best utilized?

Also, I have a question about style. I tend to put my private functions, #defines of private scope, and other data types that are not public in the .c file, the .h file only contains public functions, #defines, etc. Is this how you generally approach your files? If I understand correctly, you store all your private stuff in the _impl.h file, the public in .h and the code in .c.

These design answers are a great help to me.

RE: Sending different objects to a queue

Posted by Richard Damon on May 28, 2010
I personally try to avoid void pointers if reasonably possible, but I do realize that there are times when it just isn't possible or adds significant clutter to avoid them. One of the reasons to avoid void* pointers is that they can mask a number of errors (sending something of the wrong type, or wrong level of indirection if sending pointers to pointers). Another is if you want to inter-operate with C++ you need to realize they work differently. The main time I see them being useful is when the routine really doesn't care about the format of the memory being passed, but is going to treat it as raw bytes (and internally will probably convert the pointer to a unsigned char*, but the interface is made void* so a cast isn't needed at the call).

Of course a void* pointer could be used as one of the options.

As to style, I also tend to place private information at the top of the .c file, as long as I don't start getting too big of a file trying to keep it all together. If the file starts to get larger, then the design gets partitioned, and stuff that is needed to interconnect the pieces goes into a "private" header (which is what the _impl designates).

I do know of some organizations which have established code style guidelines that require all structure definitions to be in a header file (and sometimes each structure gets its own header file unless it is very tightly coupled with another structure). The advantage of this, particularly for a large code base, is that if you want to look up the definition/documentation for a structure, you only need to search through the .h files (and with the 1 struct per file rule, the name of the file is the name of the struct). These guidelines also sometimes have significant documentation rules for adding comments to the .h file to fully document the use and members of the struct.

Basic rule, you follow the customers guidelines.

RE: Sending different objects to a queue

Posted by jinx on May 28, 2010
Thanks for the insight into these issues.

[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]

Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS v10.2.0 is available for immediate download. MIT licensed, and including RISC-V and ARMv8-M (Cortex-M33) demos.

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


FreeRTOS and other embedded software careers at AWS.

FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Cadence Tensilica Cortes

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers





STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner