Paul & other interested programmers --
As was noted - default parameters are allowed in C++. If you look at the header file (.h), you'll see:
Code:
class JankyTask {
public:
/**
* @brief Constructor which takes an optional taskname. In the absence of a task name,
* a task name will be created based upon the current system-time.
*/
JankyTask(const char* taskName = NULL, UINT32 priority = Task::kDefaultPriority);
virtual ~JankyTask();
The constructor calls for a taskName and priority. Each of these parameters has a default value ( = NULL and = Task::kDefaultPriority) respectively. If you use the constructor without passing parameters, these defaults are used. This is a C++'ism...
As for "how it works" -- the concept is simple, the semantics can be a bit tricky, but the usage is yet again simple...
If you really are just out to "use it", then take the example and run with it by implementing your own class based on JankyTask and implement Run().
If you'd like to understand it a bit further, you'll need to understand the concept of "static functions". Most classes are defined such that instantiating the class will instantiate one of each of the functions and variables in the class definition. This is "normal" or "simple". In the case of JankyTask, you'll see that there is a static function called JankyPrivateStarterTask(). When a function is static, there is only one of them for the entire world. This becomes important here because of the way the WPILib 'Task' class works. It expects that you will hand it a function which it will "launch" as the starting function for the new task. No problem yet, right? It is of type "(FUNCPTR)". Fine - pass it a function. The problem is that in C++, each class and its functions get "name mangled" when the compiler runs and each member of a class is "private to the class" unless something special is done to it... when it is defined as "static", then it is much more like a C Function and much less like a C++ member of a class. This makes using it in Task() much easier.
When a new task is created, it needs a function to call (FUNCPTR), and when it is told to Task->Start(), it is passed a "data pointer" on its startup. This data pointer, in this case, is a pointer to the JankyTask instance. This is *SUPER* critical. This allows the JankyPrivateStarterTask to actually make a call to *YOUR* Run() function since the data pointer is for this particular instance. You'll see that task->Run() is called any time that the task is enabled within its while loop and it even does a nice 2 ms wait for you as well.
From the outside, the nice thing is that you can instantiate your JankyTask-based class and then operate it from the outside with variables telling it to Pause(), Terminate(), or to get a value, state, set a solenoid, etc.
Note: I'm glossing over a few important multi-tasking principles of how variables are used and when they need to be protected from multiple uses in multiple tasks. These are usually Mutexes or Semaphores or CriticaSections. But in the case of these simpler examples, keeping things rather un-intertwined keeps one from having to cope with these otherwise more complex ideas.
Further questions - lemme know.
:-)
Good luck at regionals this weekend! We'll be at Madera - Central Valley Regional in California. Stop by and say hi to The Janksters Team 1967.
Bob Wolff - Mentor.