Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training


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 ]    [ Sitemap ]    [ ]

Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.

Free TCP/IP and file system demos for the RTOS

Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑

FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

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

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

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

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists