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




Loading

C++ Passing varying objects from task to task

Posted by sven-de on September 5, 2011
OO-programmers listen up, I wonder if this is possible at all...
I've got an abstract base class containing some method prototypes. The derived classes implement these methods in different ways and also have different private data. There a two task: Task A creates objects of the derived classes. Task B calls the methods whose prototypes are generic, so Task B doesn't need to know which of the derived classes this object belongs to as long as it's derived from the common base class. Task B also calls the destructor after being done with the object.

My question: How can I pass on these objects from Task A to B? A Queue (with pointers) won't work, will it?

RE: C++ Passing varying objects from task to task

Posted by Richard Damon on September 5, 2011
It sounds like passing a pointer to them via a queue should work. when using FreeRTOS with C++, one thing to remember is that Queues should only be used with PODs as they use raw copying. (Actually some non-PODs can work, as long as they have trivial constructors/destructors/assignment operators).

Passing pointers can also be a good choice in C if the structure is large.

The one thing that you need to watch out with passing pointers in you need to be aware of ownership/lifetime issues, and you can't use the typical "smart pointer" for this as they don't meet the requirements for types that can be sent via queue.

RE: C++ Passing varying objects from task to task

Posted by sven-de on September 5, 2011
Hm, okay. The objects in my example certainly don't qualify as POD (plain old data).

I need polymorphism to work here. The dynamic type determination has always been magic to me, but after some research I think this could actually work. As every object contains a virtual method table (VMT), that's pointing to it's methods the bare pointer this object should be all there's necessary. These additional jumps, of course, have a performance downside but shouldn't be too crucial.

I've read this and became aware of the heap/memory implications of polymorphism:
http://www.netrino.com/node/233

So I rethought my design and came to the conclusion, that when using a queue the amount of living objects will be limited anyway. So I'm going to have a global array with fixed size and just pass on the index.

RE: C++ Passing varying objects from task to task

Posted by Richard Damon on September 5, 2011
You may have misunderstood me. A plain pointer IS a POD, so can be sent. What can't be put in are *objects* that are't PODs, which include most (all?) "smart pointer classes".

Yes, in an object that qualifies for RTTI (having a virtual function, which polymorphic classes tend to have), imbedded in the data for the object will be a VPtr, which is a pointer to a compiler built structure called the VTable (or it sounds like in your sources the VMT). (Object with multiple or virtual bases may end up with multiple VPtrs in them). If the most base class was RTTI eligible, then the VPTR tends to be the first element in the object as it is most likely the most used element of the object. Any call to a virtual method will go via this VPtr and VTable

Note, you can not create a "fixed array" of varying types, so I don't think that is actually going to be a solution.

If you make the heap protected (for example, getting new to call pvPortMalloc instead of malloc directly) then task A could just create a new object with new, pass the pointer via a queue to task B, and then task B could delete the object. This may be the "simplest" option, assuming you can make new/delete safe and can tolerate the issues of using a heap in a "real time" program.

Another option is to create pools of the various object that need to be sent, and task A "checks out" an object from the appropriate pool, and when task B is done, it checks it back in (probably via a member function of the object, as it should know which pool it came from).

RE: C++ Passing varying objects from task to task

Posted by sven-de on September 7, 2011
Thanks for clearing that misunderstanding. A pointer is of course POD.

I'd really like to avoid messing around with heap, because I don't believe I have to. Can't I define a fixed number of memory slots, each big enough to hold the largest of all possible objects (this size is known at compilation time) and then just place varying objects in these slots, like a ring buffer? That's been the idea behind aforementioned array...

(I once more appologize for going off-topic in regard to FreeRTOS)

RE: C++ Passing varying objects from task to task

Posted by Richard Damon on September 7, 2011
Yes, if you do not want to use the heap, you can use preallocated buffer. You can then use "placement new" to convert a slot of raw memory into the object and pass a pointer to that new object to the next task. It is best to declare such a buffer as an array of char, and you can make your ring buffer an array of these arrays of char, or a single array of char with a large enough size to hold the multiple objects.

Passing the pointer instead of the index still make sense as you can not use the index to just access the ring buffer (since that will get you an array of char as its type), and would still need to convert that address into a pointer. It also localizes how much code needs to know how the objects are allocated incase at some point in the future you want to change it.

In case you are not familiar with "placement new", the format of it is new(buffer) Type where buffer is a pointer to the raw memory to use. To release the memory you just explicitly call the objects destructor and somehow let your allocation routine know that the slot is empty.

RE: C++ Passing varying objects from task to task

Posted by sven-de on September 14, 2011
Dear Richard,
thank you for that hint about placement new. That's exactly what I've been looking for - but obviously with the wrong search terms. I also successfully redirected new and delete to pvPortMalloc() and vPortFree(), which was rather unspectacular:
void *operator new(size_t size) throw() {
return pvPortMalloc(size);
}
void operator delete(void *p) throw() {
vPortFree(p);
}


Now my Linker complains about undefined references to VTables, which I shut off by adding the copiler-flag -fno-rtti. So far I haven't run into trouble, but also didn't do any thorough testing. Is that legal, or do I need RTTI for polymorphism? Most documentations say, that it's only required for and typeinfo()...

RE: C++ Passing varying objects from task to task

Posted by Richard Damon on September 14, 2011
you should only need RTTI for dynamic_cast<> and type info(), polymorphism just needs the base vtable. Not sure why your linker was complaining about the references to VTables, you may have had some other options in a bad combination.

For completeness, you should also replace operator new[](size_t) and operator delete[](void*) to use the Port Layer allocators.


[ 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