diff --git a/include/maestro/i_cdo.h b/include/maestro/i_cdo.h index d4e2fbd4203dee4eda01434746b401bca5126270..93f20dabdbec4ee7becdf4c5de4b2d37fd3b6ae1 100644 --- a/include/maestro/i_cdo.h +++ b/include/maestro/i_cdo.h @@ -156,7 +156,14 @@ typedef uint32_t mstro_cdo_state; /** The NIL UUID */ #define MSTRO_CDO_ID_INVALID { .id = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 } } -/** return a string describing the CDO state @arg s */ +/** return a string describing the CDO state @arg s + ** + ** The string is owned by this function, but this function can safely + ** be called from multiple threads (the buffer is thread-local). The + ** buffer will be re-used by subsequent calls in the same thread + ** after a small number of invocations (currently: 3, see @ref + ** MAX_STATE_DESCRIPTION_BUFFERS). + **/ const char * mstro_cdo_state_describe(mstro_cdo_state s); diff --git a/maestro/cdo.c b/maestro/cdo.c index 867151da57d7c737e0658ceea7c34ea9f3d879bf..8ec685e4af995885e05df2eb9db64812d32c239e 100644 --- a/maestro/cdo.c +++ b/maestro/cdo.c @@ -1633,22 +1633,34 @@ struct { /** a reasonably safe way to count the number of entries in an array of structures */ #define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +/** we support this many concurrent state buffers in flight per + * thread. Hideous, but callers typically will use this function in a + * PRINT statement, with up to two states (to compare them) at most + */ + +#define MAX_STATE_DESCRIPTION_BUFFERS 3 const char * mstro_cdo_state_describe(mstro_cdo_state s) { - static _Thread_local char buf[sizeof(states_and_names)]; + static _Thread_local char buf[MAX_STATE_DESCRIPTION_BUFFERS][sizeof(states_and_names)]; + static _Thread_local size_t bufid = 0; - buf[0]='\0'; + // switch to new buffer + bufid = (bufid+1) % MAX_STATE_DESCRIPTION_BUFFERS; + + buf[bufid][0]='\0'; if(s==MSTRO_CDO_STATE_INVALID) return "INVALID"; else { for(size_t i=0; i<COUNT_OF(states_and_names); i++) { if(s&states_and_names[i].state) { - strcat(buf, states_and_names[i].name); + strcat(buf[bufid], states_and_names[i].name); } } - return buf+1; /* cut off leading '|' we put there for simplicity + + return buf[bufid]+1; /* cut off leading '|' we put there for simplicity * of the loop above */ } }