execution queue

I'm new to C so I get to ask dumb questions.
I'd like to set up an execution queue. I don't see a way to call a routine
from a variable ( an indirect call ).
Both switch case and a pile of if's are too inefficient. They would have to hold
each possible execution when a queue might only have 1 or 2
at any one time.
I want to place a number of things into an ordered task queue and
each would wait for its time to execute.
This way I could have 100's of things in the queue and
each would know when it was to execute or as few as a single
task, at any one time.
Dwight

Google 'pointers to functions' I think is what you want.

dwightthinker:
Both switch case and a pile of if's are too inefficient.

There's a big difference between "means I have to type a lot" and "produces inefficient code." I think you may mean the former because switch case statements are hardly inefficient.

Can you show us pseudo code as to what you want to do?

Are you wanting to simulate multitasking?

Hundreds of tasks seems to be pushing the limits of a micro controller, but if you limit that to about 25, then it should be able to do it.

Okay, "execution queue" is not the right phrase because that is a FIFO structure. But your idea is possible to implement. It might be an interesting way to handle a lot of timed events. Try it and get back to us.

The queue can be the loop() function. List your functions in order as you want them executed. And, when it gets to the bottom of the list it will start over.

Okay, this thread is going to get a lot of different advice because you haven't clearly explained what you are trying to do.

Normally in Arduino programming, the tasks are prioritised. You have a main task like checking the door-opener hasn't hit its limit switches, which must be checked thousands of times per second. If there's serial data coming in, that comes in so slowly that you can make that a low-priority task.

void loop() {
  if(LimitSwitchesTouched()) stopMotor();
  if(StartButtonPushed()) startMotor();
  if(TimeToBlinkLED()) digitalWrite(LEDPIN, !digitalRead(LEDPIN));  //this flips the state of the output pin
  if(Serial.available()) processIncomingChar(Serial.read());
}

In this example, the function which processes an incoming character must be relatively quick, so it doesn't 'block' the limit switch checker for more than a millisecond or so.

It has been assumed that any one task is only executed once when it might be queued up several time.
Also the sequence of evens is also not necessarily in any particular order, although some
threads of operations might be in order.
A FIFO is not quite what I has in mind. A linked list is more what I had in mind.
I'm not as worried about time to queue up an event as I am about how fast it would execute
once it was time to do so.
I have a 2560 with 256K of space to have execution code so that number of task is not an issue.
I've done such things in the past in assembly code but not on a Harvard machine.
Dwight

Then an array or linked-list of function pointers might be the way to go. Or just use a integer numbered tasks and a switch statement:

void loop() {
  int TaskNum = getNextTaskFromQueue();

  switch(TaskNum) {
    case 1:
      doTask1();
      break;
    case 2:
      doTask2();
      break;
    //...
  }
}

Linked lists use more memory than an array, on an Uno you have very limited RAM so go
with an array.

Using function pointers mean having to understand C's bizarre inside-out notation for types of
functions, which is one of C's most confusing parts.

dwightthinker:
A FIFO is not quite what I has in mind. A linked list is more what I had in mind.

Note that Fifo denotes the way you access a data structure (first in, first out)
while linked list denotes a data structure implementation.

It seems that you have missed the point of my reply #6, which requests that you explain what you are trying to do. Instead you are continuing to talk about how you will implement your scheme.

Also you are still using terminology like "queue up" yet you have asserted that you do not want to use a FIFO.

Please explain the aim or goal of this code, as if you were asking someone else to write it. Otherwise, we will have another thread of aimless guessing that will never help you solve your problem.

Dinamic

typedef void(*LOOP)(void);

struct task
{
    LOOP fnc;
    struct task* next;
};

struct task tfirst = NULL;

void task_push( struct task* t)
{
    t->next = NULL;
    if ( !tfirst )
    {
        tfirst = t;
        return;
    }
    struct task* l = tfirst;
    for(; l->next; l = l->next);
    l->next = t;
}

struct task* task_pop(void)
{
    struct task* ret = tfirst;
    if ( tfirst ) tfirst = tfirst->next;
    return ret;
}

void loopA(void)
{
    ...
}

struct task tA = { loopA, NULL };

void loopB(void)
{
    ...
}

struct task tB = { loopB, NULL };



void setup(void)
{
    task_push(&tA);
    task_push(&TB);
}

void loop(void)
{
    struct task* cur = task_pop();
    if (!cur) return;
    cur->fnc();
    task_push(cur);
}

Fixed

typedef void(*LOOP)(void);

void loopA(void)
{
    ...
}

void loopB(void)
{
    ...
}

LOOP task[] = {loopA, loopB, NULL};
int itask = 0;

void setup(void){}

void loop(void)
{
    if ( NULL == task[itask] ) itask = 0;
    task[itask++]();
}

I think vbextreme's dynamic is close to what I'm after.
I don't have an immediate need but may in the future.
As an example, I did a burning system for power laser diodes.
It needed to run up to 50 PID temperature controls and 50 current controls
based on current temperature of a bank of diodes.
While doing this it also ran a used interface that was used to determine
which blocks of diodes were loaded and needed to be turned on.
It also needed to know when a block of diodes was done with the specified
duration of burning.
The entire thing was run with one Z80 processor.
The PID loops need a consistent time to check each A/D reading. Other task
such as checking current ramping to temperature need to be checked to
make sure that current was max for that temperature. All the while each
block that was turned on had a specific minimum time that is needed to run
( not as critical as PID and current monitor but still within seconds ).
I knew exactly how much time each task took and what was budgeted for
each. The system had to preform that same if all 50 blocks of diodes were
loaded or only one was loaded.
Checking to see if a block was loaded and if it was turned on and what it
temperature was and if it had completed is time as a string of ifs used up too
much time.
By putting the timed task into the linked list each task would only need to
be ordered in the list so that when it came to the front of the list it executed.
The user interface was allowed part of the time when there were gaps big
enough to complete the more simplified actions they needed. People are
generally slower than computers.
Dwight

It is impressive that you created assembly code for the Z80 to do so much.

Can you also create a few lines of pseudo code to show how you want the arduino/C to do your task(s) ?

This is what I think the Original Post is saying....

Several functions are defined (perhaps a large number) funcA() funcB() funcC() etc.

There needs to be a list (similar to an array, perhaps) which contains the order in which the functions are to be called. Something like this pseudo code
funcAray = {funcB, funcA, funcB, funcA, funcC}

Then loop() can iterate over that "array" like this pseudo code

void loop() {
   call function(funcArray[n]);
   n ++;
   if (n >= nMax) {
      n = 0;
   }
}

If that is a reasonable description of the requirement then I suspect it can be implemented using an array of function pointers.

What is not clear is where timing comes into the picture. Does the OP want each function to run once only (easily achieved) at a specific time (easily achieved using millis() ) or must each function contain its own timing arrangements (which can also probably be achieved with millis() )?

It is also not clear how the list of functions is created. Does the OP want to do that before the program is compiled (relatively easy) or at run time (I don't immediately know how to do that).

...R

We can guess all month what the OP wants.
I can't see a use for having functions in an array, since the loop() function acts as a queue, and allows conditional statements also. EG:

loop() {

if more than a milli second since last door read, checkDoor();
if door opened, doAlert();
if time to read voltage, readVoltage();
if new text available, printToLCD();

}

loop() will execute faster, about 50,000 times a second.

Not only is it faster, more flexible, but it is more readable. Just my opinion.

Maybe the OP has a different opinion.

Exactly my point. Saw it coming.

Expressing it differently can sometimes bring clarity - even if only to say "not like that, like this"

But we await the pleasure of the OP.

...R