One of the things that I’ve always wished I could do with my Arduino is writing programs that can do multiple tasks independently of each other. Unfortunately, the Arduino doesn’t support multi-threading. Instead, I’ve written a library to provide crude multi-threading support.
This is actually based on an idea I had back in around ’97, but I’ve made some modifications to adapt it for the Arduino. For instance, I’ve trimmed the code down so that it can run in the smallest memory footprint possible since Arduinos don’t have a whole lot of memory to spare.
Anatomy of a Typical Arduino Program
In order to understand what this library does, it is important to first understand what a typical Arduino program looks like.
A typical Arduino program has two main functions. First there is a setup() function that is called once when the system is powered on. This is typically used for initializing variables, setting pins as input or output, starting up serial communication, etc. Once the setup() function completes, there is then a loop() function that just gets called again and again and again and again… until the system loses power or breaks down.
So What Does this Library Do Differently?
First of all, a program that uses this library has no main loop() function (well, it does, but it’s part of the library; it doesn’t have to be separately written).
Instead, the library provides a Thread class. This class can be derived from to provide the basic functionality for a single thread. Each Thread has its own loop() function which works in basically the same way as the loop() function we all know and love. The only major difference is that the loop() function in a Thread returns a boolean value (true if the loop needs to be called again or false if it doesn’t). When the Thread completes, it will automatically destroy itself freeing the memory it occupied to be used for other things.
Once a Thread object is created, it then has to be added to a ThreadList object (through the add_thread() function). One of these is already created by the library. It’s called main_thread_list and it’s run in place of the main loop() function.
What a ThreadList does is call the loop() function from the first Thread in the list, then it calls the loop() function from the next one, and so on and so forth. Once they’ve all been called, it returns to the first Thread and starts over again. Whenever a Thread has completed its run, it is automatically removed from the ThreadList.
An interesting thing about ThreadLists is that they are Threads in and of themselves. That way a tiered system can be crated where a lower-priority ThreadList object can be placed inside of a higher one. That way, the higher-priority ThreadList will call one loop() from each of the high-priority Threads, and then a loop() from the first Thread in the lower-priority list. It will then call the loop() function in all of the high-priority Threads again, and then the next one from the low-priority list… and so on.
The kill() Function
Rather than waiting for it to run its course, a Thread can be killed by calling its kill() function. There are two levels of “kill” that this function offers. The first (recommended) way is much more polite. It simply sets an internal variable called kill_flag to true telling the Thread that it should start finishing up. Its loop() function is expected to check for this and behave accordingly.
The second way of killing a Thread is to call kill(true). This will essentially kill the Thread outright without any warning. Do not use the delete keyword on a Thread! This will cause memory corruption.
One of the major potential problems with this library is the fact that a single Thread that gets hung will lock the entire system up, since the next Thread can’t be called until the current one finishes its loop() function.
For this reason, it is unwise to use blocking functions such as delay(), because they will cause a delay in all the other threads as well. To help get around this, the Thread class has three functions that will not allow the loop() function for that Thread to be called again until a specified amount of time has passed. These functions are sleep(), sleep_milli() and sleep_micro(); which suspend the Thread for a set number of seconds, milliseconds and microseconds respectively.
The Thread class also provides pause() and resume() functions. As the names imply, the pause() function will suspend the Thread until the its resume() function is called. Obviously, the resume() function would have to be called by another (non-suspended) Thread, so care should be taken with these functions.
Where Can I Get It?
Hopefully, this will be useful to someone other than me.
I almost forgot to mention that this library also requires another simple library called newdel to enable the new and delete keywords. It’s available (public domain) here.
Moved the project to github and updated the links.
This library is now available under the Lesser General Public License (verion 3 or later).