Thread locals don't fully solve the problem. They work well if you immediately call the closure, but what if you want to store the closure and call it later?
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
typedef int (*comp)(const void *untyped_left, const void *untyped_right);
thread_local int in_reverse = 0;
__attribute__((noinline))
int compare_impl(const void *untyped_left, const void *untyped_right, int in_reverse) {
const int* left = untyped_left;
const int* right = untyped_right;
return (in_reverse) ? *right - *left : *left - *right;
}
comp make_sort(int direction) {
in_reverse = direction;
int compare(const void *untyped_left, const void *untyped_right) {
return compare_impl(untyped_left, untyped_right, in_reverse);
}
return compare;
}
int main(int argc, char* argv[]) {
int list[] = { 2, 11, 32, 49, 57, 20, 110, 203 };
comp normal_sort = make_sort(0);
comp reverse_sort = make_sort(1);
qsort(list, (sizeof(list)/sizeof(*list)), sizeof(*list), normal_sort);
return list[0];
}
Because we create `reverse_sort` between creating `normal_sort` and calling it, we end up with a reverse sort despite clearly asking for a normal sort.
The answer is you wrap it and you don’t return until the thing stored in the thread local is not needed