C++ Passing varying objects from task to task

sven-de wrote on Monday, September 05, 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?

richard_damon wrote on Monday, September 05, 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.

sven-de wrote on Monday, September 05, 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:

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.

richard_damon wrote on Monday, September 05, 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).

sven-de wrote on Wednesday, September 07, 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)

richard_damon wrote on Wednesday, September 07, 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.

sven-de wrote on Wednesday, 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() {

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 <dynamic_cast> and typeinfo()…

richard_damon wrote on Wednesday, 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.