This is the second part of this series. In part I I tried to explain how to objectify tasks for the FreeRTOS framework. In that approach I’ve used dynamic polymorphism. In this post I’ll implement the same solution but using static polymorphism through the use of the C++ CRTP pattern.
Modifying the (not anymore) abstract base class Thread
While coding this solution I renamed the base class as ThreadX (as well as the inherited classes) in order to the client be able to use the version (dynamic or static) that fits the most its particular needs. Let’s see the result:
We have three major changes. 1) The base class is templatized; 2) and because the use of the CRTP pattern ThreadX class isn’t an abstract class anymore (well, it’s still an abstract base class in our minds, and maybe we can hide the constructor so no one can instantiate objects from it); 3) the trampolin member function Main() isn’t virtual anymore either.
Base class templatized. In order to implement the CRTP pattern the base class needs to be templatized so it can use the member functions from the inherited classes. In this fashion Main() turns into a regular member function. In line 54 we derreference the this pointer and then we cast it to the type of the inherited class, so we are able to reference the actual object that made the call to Main(). The code in line 54 could’ve been written as:
The concrete classes must be adapted to the CRTP pattern, as shown:
In this class we see two major changes: 1) In line 67 we declare the class LedX to be inherited from class ThreadX, and at the same time, a special version of it is created through something like: class Thread<LedX>. The other change can be seen in line 78. Again, the member function Main() is a regular one.
Finally, we create objects as usual:
Does it really work?
Yes, and it’s awesome, indeed. Even more, you can use this approach, or that from the part I, without understanding a single line from the base class Thread(X); just stick to the “rules” for the inherited classes.
My non-scientific tests have shown that, at least for the program’s size, that one can say there is not so much difference between the two approaches. To be exact, dynamic polymorphism uses 6168/8 flash/ram, whilst static polymorphism uses 6096/4.
- The same two approaches but for static tasks, xTaskStaticCreateTask().
- To objectify the FreeRTOS’ timers.
I don’t already have a git repo for this approach, but you can get the source code shown in this post from here.