in inc/c_util/async_retry_wrapper.h [463:528]
static void ASYNC_RETRY_WRAPPER_CALLBACK(async_function_name)(void* context ASYNC_RETRY_WRAPPER_CALLBACK_ARGS_DECLARATION_PROXY(out_args)) \
{ \
if (context == NULL) \
{ \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_42_016: [ If context is NULL, on_{async_function_name}_complete shall terminate the process. ]*/ \
LogCriticalAndTerminate("NULL context for " MU_TOSTRING(async_function_name) " callback"); \
} \
else \
{ \
ASYNC_RETRY_WRAPPER_CONTEXT(async_function_name)* retry_context = context; \
ASYNC_RETRY_WRAPPER_GET_ENUM_TO_CHECK_PROXY(out_args) \
if (ASYNC_RETRY_WRAPPER_RETRY_CONDITIONS_PROXY(retry_async_enums)) \
{ \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_02_003: [ If the out_arg specified as ENUM(type, name, error_value) has one of the values from RETRY_ON_ASYNC(...) and the the time measured from the initial call to ASYNC_RETRY_WRAPPER() exceeded timeout_ms then the user callback specified in ARG_CB(...) shall be called, passing the context from ARG_CONTEXT(...), and the out_args as they were received by this callback handler with the exception of the ENUM(...) which will have the value specified for timeout_error_value. ]*/ \
bool timed_out = false; \
if (retry_context->timeout_ms < UINT32_MAX) \
{ \
double elapsed_time_ms = timer_global_get_elapsed_ms() - retry_context->start_time; \
if (elapsed_time_ms + retry_context->backoff > retry_context->timeout_ms) \
{ \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_42_049: [ Before each retry of the function, If timeout_ms milliseconds have elapsed then {async_function_name}_async_retry_wrapper_with_timeout shall fail and return ASYNC_RETRY_WRAPPER_TIMEOUT. ]*/ \
LogError("Retries for " MU_TOSTRING(async_function_name) " timed out after %lf ms (including %" PRIu32 " ms of backoff) (timeout time was %" PRIu32 " ms)", \
elapsed_time_ms, retry_context->backoff, retry_context->timeout_ms); \
timed_out = true; \
/* Codes_SRS_ASYNC_RETRY_WRAPPER_01_001: [ If any error occurs, on_{async_function_name}_complete shall call the user callback specified in ARG_CB(...), passing the context from ARG_CONTEXT(...), and the error_value from all of the ARG(type, name, error_value)'s in out_args. ]*/ \
retry_context->user_captured_callback(retry_context->user_captured_callback_context ASYNC_RETRY_WRAPPER_CALLBACK_ARGS_FOR_CALL_WITH_TIMEOUT_PROXY(out_args));\
ASYNC_RETRY_WRAPPER_FREE_FIELDS_PROXY(in_args); \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_11_001: [ on_{async_function_name}_complete shall assign the threadpool to NULL. ]*/ \
THANDLE_ASSIGN(THREADPOOL)(&retry_context->threadpool, NULL); \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_42_021: [ on_{async_function_name}_complete shall free the allocated context. ]*/ \
free(retry_context); \
} \
} \
if(!timed_out) \
{ \
LogVerbose("Scheduling retry of " MU_TOSTRING(async_function_name)); \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_42_017: [ If the out_arg specified as ENUM(type, name, error_value) has one of the values from RETRY_ON(...) then on_{async_function_name}_complete shall call threadpool_schedule_work with {async_function_name}_do_retry as the work_function to retry the asynchronous call and return. ]*/ \
if (threadpool_schedule_work(retry_context->threadpool, ASYNC_RETRY_WRAPPER_RETRY_FUNC(async_function_name), retry_context) != 0) \
{ \
LogError("threadpool_schedule_work failed for " MU_TOSTRING(async_function_name)); \
/* Codes_SRS_ASYNC_RETRY_WRAPPER_01_001: [ If any error occurs, on_{async_function_name}_complete shall call the user callback specified in ARG_CB(...), passing the context from ARG_CONTEXT(...), and the error_value from all of the ARG(type, name, error_value)'s in out_args. ]*/ \
retry_context->user_captured_callback(retry_context->user_captured_callback_context ASYNC_RETRY_WRAPPER_CALLBACK_ARGS_FOR_CALL_WITH_ERROR_PROXY(out_args)); \
ASYNC_RETRY_WRAPPER_FREE_FIELDS_PROXY(in_args); \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_11_001: [ on_{async_function_name}_complete shall assign the threadpool to NULL. ]*/ \
THANDLE_ASSIGN(THREADPOOL)(&retry_context->threadpool, NULL); \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_42_021: [ on_{async_function_name}_complete shall free the allocated context. ]*/ \
free(retry_context); \
} \
else \
{ \
/* All OK, will execute on threadpool callback */ \
} \
} \
} \
else \
{ \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_42_018: [ on_{async_function_name}_complete shall call the user callback specified in ARG_CB(...), passing the context from ARG_CONTEXT(...), and the out_args as they were received by this callback handler. ]*/ \
retry_context->user_captured_callback(retry_context->user_captured_callback_context ASYNC_RETRY_WRAPPER_CALLBACK_ARGS_FOR_CALL_PROXY(out_args)); \
ASYNC_RETRY_WRAPPER_FREE_FIELDS_PROXY(in_args); \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_11_001: [ on_{async_function_name}_complete shall assign the threadpool to NULL. ]*/ \
THANDLE_ASSIGN(THREADPOOL)(&retry_context->threadpool, NULL); \
/*Codes_SRS_ASYNC_RETRY_WRAPPER_42_021: [ on_{async_function_name}_complete shall free the allocated context. ]*/ \
free(retry_context); \
} \
} \
}