Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequential Execution of functions with break option

I have a thread in my operating system that is called in a fixed interval and then executes a list of 10-15 distinct functions sequentially. Each function has a return parameter that either says 0 (OK) or not 0 (error). Looks something like this:

while (1) {
    error &= function_1();
    error &= function_2(some_parameter);
    error &= function_3();
    handleError(error);
}

However it would be preferred that when one of the functions returns an error, the error is handled immediately and the other functions are not being executed anymore (single error failure).

For two functions I could do an if condition before each function but for 10-15 that would lead to a lot of unnecessary ifs.

For that I would use an array of function pointers that I go through sequentially:

int (*p_functions[3])() = { function_1, function_2, function_3 }
while (1) {
    for (int i = 0; i < 3, i++) {
        error = p_functions[i];
        if (error) {
            handle_error(error);
            break;
        }
    }
}

My issue here is that as you can see in the first example my function_2() has a parameter that gets maybe generated by another function beforehand. So I can't deal with functions that have different parameters.

Are there any other ways to solve that? Or maybe with some tricks for pointer casting? I heard dirty casting is a thing?

like image 418
Julian Avatar asked Dec 31 '25 16:12

Julian


2 Answers

Given a function that returns 0 on success and 1 on error, you can change the existing code to use ||, which has short circuit behavior and more closely matches what you want to do anyway, instead of &:

while (1) {
    error = error || function_1();
    error = error || function_2(some_parameter);
    error = error || function_3();
    handleError(error);
}

Now, once error is set to 1, no further functions will be called.

As far as handling a specific error, you can set the variable with a function's return value shifted a certain amount based on which function failed, then check the bitmap in the error function.

uint32_t error_map = 0;
while (1) {
    error_map || (error_map |= (function_1()                << 0));
    error_map || (error_map |= (function_2(some_parameter)  << 1));
    error_map || (error_map |= (function_3()                << 2));
    handleError(error_map);
}

Then in handleError:

if (error_map & (1<<0)) {
    // function 1 error
}
if (error_map & (1<<1)) {
    // function 2 error
}
if (error_map & (1<<2)) {
    // function 3 error
}

If the functions could return any non-zero value on error, you can capture that error code in a separate variable:

uint32_t error = 0, error_map = 0;
while (1) {
    error_map||(error_map |= (((error = function_1()) != 0)               << 0));
    error_map||(error_map |= (((error = function_2(some_parameter)) != 0) << 1));
    error_map||(error_map |= (((error = function_3()) != 0)               << 2));
    handleError(error, error_map);
}

And the above with a macro to make it more readable:

#define RUN_ON_NO_ERROR(error, error_map, index, call) \
  ((error_map)||((error_map) |= ((((error) = (call)) != 0) << (index))))

uint32_t error = 0, error_map = 0;
while (1) {
    RUN_ON_NO_ERROR(error, error_map, 0, function_1());
    RUN_ON_NO_ERROR(error, error_map, 1, function_2(some_parameter));
    RUN_ON_NO_ERROR(error, error_map, 2, function_3());
    handleError(error, error_map);
}
like image 81
dbush Avatar answered Jan 02 '26 04:01

dbush


#define E(e,x)  e = (e ? e : x)
while (1) {
    error = 0;
    E(error, function_1());
    E(error, function_2(some_parameter));
    E(error, function_3());
    handleError(error);
}

Isn't too bad; this is the style things like the SV test suite are written in; and the actual error value is preserved.

like image 35
mevets Avatar answered Jan 02 '26 04:01

mevets