I am looking for a solution that is fast and still readable. I have to do this in C but the code will be static in the end, which mean I could use any tool to generate it.
I have a task which runs cyclically and calls different functions also cyclically
Main functions cycle is 1.
Function a has also cycle 1. So the main function calls it every time
Function b has cycle 2. Main function calls it every second cycle.
Function c has cycle 2.
Function d has cycle 4.
Function e has cycle 4.
Function f has cycle 4.
Function g has cycle 4.
… many more ….
Function X has cycle 500.
If we have many functions that run in the same cycle we try to distribute them.
So for function b we would call it in one cycle and c in the other. Distributing the load evenly.
Similar for d to g. Each one gets called in a different cycle.
My current implementation is very bad.
Every developer who had to add their task to main function calculates their on modulo and calls when needed. This leads to a very unreadable code.
I was thinking of doing something like:
uint32 mod4 = timer % 4;
bool fourth_1 = mod4 == 0;
bool fourth_2 = mod4 == 1;
bool fourth_3 = mod4 == 2;
bool fourth_4 = mod4 == 3;
bool second_1 = fourth_1 || fourth_3;
bool second_2 = fourth_2 || fourth_4;
/* and so on*/
But this seems cumbersome and too error prone specially as the highest cycle time is too high.
How to approach this kind of problem?
-Edit-
As asked i have compiled some information about the number of functions that i have:
- 32 functions cycle 1
- 9 functions cycle 2
- 14 functions cycle 4
- 3 functions cycle 8
- 3 functions cycle 32
- 3 functions cycle 40
- 2 functions cycle 200
- 2 functions cycle 400
2
The starting point for solving this problem is a data structure. The elements of the structure are nodes (structs) containing:
- how to call one of the functions: a function pointer, any arguments, any other information
- when to call a function: the ‘cycle’ as you put it.
You can use a flat list created at compile time, but then the entire list will have to be searched at least once for each cycle, and that may not be good for performance. A better approach is to add each node to a data structure designed to minimise searching. I would suggest a list for each cycle modulo, so 8 lists for the data given.
- At initialisation time add each function node to the list(s) on which it should be called.
- On each cycle simply go down the list(s) that are applicable, calling each function in turn.
Simple, testable, maintainable, extensible.
I may have your definition of “cycle” wrong. If “Cycle N” means that a method should be called when “timer” modulo N is 0, why not put pointers to those functions into a list or array of structure instances, and include in each structure, the “N” you want to modulo? Then after you increment “timer”, check each structure to see if modulo N is 0. If so, invoke the function pointer.
After reading the problem description, I see that “Cycle N” has the additional restriction that only one function can run at once for a given N. To satisfy this requirement, keep an additional flag, “last run”, in the structure mentioned above. Put each structure for a given N value in a separate list or array. This way you can mark the last run function, then unmark that one, run the next one, mark it, and so on, each time through.