ivanseidel / ArduinoThread

⏳ A simple way to run Threads on Arduino
MIT License
955 stars 196 forks source link

Library name is misleading #5

Closed edgar-bonet closed 9 years ago

edgar-bonet commented 9 years ago

I have witnessed some confusion caused by the name of this library, with people wondering whether it implements threads. I would argue that this library should better be renamed, because it has nothing to do with threads.

The whole purpose of threads is to simplify programming by allowing the use of blocking functions and infinite loops, without fear of blocking the whole program. For example, blinking an LED with threads would be done like this:

void blink_led()
{
    pinMode(ledPin, OUTPUT);
    for (;;) {              // infinite loop is OK
        digitalWrite(LedPin, HIGH);
        delay(200);         // only this thread is blocked
        digitalWrite(LedPin, LOW);
        delay(200);         // ditto
    }
}

The competing paradigm is the state machine, where one has to remember the current state, and write non-blocking tasks that perform one single state transition on each call:

void blink_led() {
    static bool initialized;    // state variable
    static bool ledState;       // ditto

    if (!initialized) {
        pinMode(ledPin, OUTPUT);
        initialized = true;     // update state
    }
    ledState = !ledState;       // update state
    digitalWrite(ledPin, ledState);
}

The whole purpose of this library is to support this style of programming by taking care of the scheduling of these tasks.

Since threads and state machines are competing paradigms, and since this library is specifically designed to support the latter, calling it “ArduinoThread” is misleading. Granted, the README file starts by saying that these are not “real” threads, but it stills gives the feeling that this is somehow related to threads, or that we may have some sort of “quasi-threads”, maybe like protothreads. One has to completely understand the library in order to see that we are actually in the “opposite camp”.

It is worth noting that protothreads can be used on Arduino, and that “real” threads have been implemented on AVR microcontrollers in the form of preemptive multitasking kernels: here and here.

ivanseidel commented 9 years ago

Thread in translation, means "wire", or a "timeline". That is what this library is about, having multiple timelines in a single program, in a good manner, without a complex wrapper that have many odds.

Time lines running in parallel, are not even "real" in real Multi-core computers, since it has mostly up to 4 or 8 cores, and running more than 100 also called "threads".

This is done by a fast-switching and also process controller, that manages those snippets of code and give time space to process all of them.

Old micro-controllers, also used this pattern to provide robust and "independent" processes.

Threading, is all about running multiple codes. Unfortunatelly, I didn't have time to implement a "yeld" method, but that has been done by the Arduino Library itself.

I wanted to name it ArduinoThread, because for me it was intuitive, altought for expert users it might not seem that. The core of the library is really simple, and as shown in my videos also, I have implemented a timing method and then said: "Hey, if you don't want to waste your time, this library has done it for you".

People should read the docs (that are pretty clear). Also, no ones looks for "Scheduler" in the goole unless they know what they are looking for, "Thread" is most searched Keyword.

To finish, changing the name is not an option, since it has been referenced in many places, and it's largely used today. It would just mislead people into a 404 page, and also mislead who already downloaded it and comes to check it out.

Thank you very much for the suggestion, but unfortunately I can't accept it. I think you will understand.

But if you feel engaged to this project, we might discuss putting in practice the "Part 2" of it:

A extension that allows Thread's to "yeld" to another threads in the current ThreadController context and also, a switching method that can be called from within an interruption.

This would allow for example, something like this (That I think is amazing, and is really simple to use, without having to be tighten up to a library structure that is hard to change):

void timerHandler(){
 // If runner is running something, it saves the context (registers), and switch to other
 // If that thread is called again, it will continue from where it was
 // In this way, you can do loops within Threads...
  runner.switchContext();
}

Thread thrA(..., ...);
Thread thrB(..., ...);
ThreadController runner;
void setup(){
  // Adds threads to runner
  // Start timer
} 

void loop(){
  runner.run();
}

I haven't tought deep into it, but just by having an overview, I can see some problems. I didn't found the best solution, yet.

Best,

edgar-bonet commented 9 years ago

The word “thread” has indeed several meanings. However, in the specific context of computing, this is a very well established term with a pretty clear meaning. Too well established for you to redefine it on the basis of etymology or “intuitiveness”. Also, renaming the library does not mean leaving a 404 behind, as that's what redirects are for.

Anyway, I perfectly understand you may not want to give away the search engine advantage of the word, so I will not insist any further on the renaming.

There is, however, something that can be done to mitigate the problem: make the documentation very clear about what this is and is not. The documentation, as it is, already has all the information the user needs to use the library. It is also clear enough... if you read it entirely! My point is that one should not have to read the entire documentation to know what the library is about: it should be clear from the opening paragraphs. Right now, the very first sentence of README.md, “Arduino does not support "REAL" parallel tasks (aka Threads), [...]” is ambiguous. There are at least two possible readings, depending on how you interpret the word “Arduino”:

  1. The Arduino hardware cannot support real threads, this library provides an alternative solution for the kind of problems where one may want to use threads.
  2. The Arduino software does not provide real threads, this library fills this gap by providing them.

And both of these readings are incorrect... I think the opening of the README should be rewritten to make clear that this library does not provide real threads, it provides an alternative. It should probably also state that this solution is very lightweight, especially in RAM consumption, compared to what real threads would be, just to make clear that not being “real” threads is not necessarily a bad thing.

OK, let me give it a try:

ArduinoThreads is a library for managing the periodic execution of multiple tasks.

Blinking an LED is often the very first thing an Arduino user learns. And this demonstrates that periodically performing one single task, like toggling the LED state, is really easy. However, one may quickly discover that managing multiple periodic tasks is not so simple if the tasks have different execution periods.

ArduinoThreads is designed to simplify programs that need to perform multiple periodic tasks. The user defines a Thread object for each of those tasks, then lets the library manage their scheduled execution.

It should be noted that these are not “threads” in the real computer-science meaning of the term: tasks are implemented as functions that are periodically run to completion. On the one hand, this means that the only way a task can “yield” the CPU is by returning to the caller, and it is thus inadvisable to delay() or do long waits inside a task. On the other hand, this makes ArduinoThreads memory friendly, as no stack needs to be allocated per task.

As for your “Part 2”, sure this is exiting, and sounds like real preemptively scheduled threads. For an AVR implementation, you may want to look at the links I provided for preemptive multitasking kernels. Providing a portable implementation (for the ARM-based Due, the i386-based Galileo, ...) would certainly not be so easy... You may want to take a look at the GNU Portable Threads library. It is based on the standard setjmp/longjmp functions, which should be available on any Arduino, but it seems to also require the less common sigaltstack.

ivanseidel commented 9 years ago

I like the idea of clarifying on the README.

Do you want to commit that, or should I?

I believe it can become a section just bellow the introduction, with that same title.

(Reopening so that we can use this issue)

edgar-bonet commented 9 years ago

I think I will let you commit. You may want to reword, as this was only a suggestion.