diff --git a/include/bal_engine.h b/include/bal_engine.h index d7eed32f..d5b637c6 100644 --- a/include/bal_engine.h +++ b/include/bal_engine.h @@ -113,6 +113,11 @@ extern "C" /// Returns [`BAL_ENGINE_ALREADY_RUNNING`] if the thread is still running. BAL_HOT bal_error_t bal_engine_run_thread(bal_engine_t *engine); + /// Stops the engine execution asynchronously. + /// + /// This function is thread-safe and can be called from any thread. + BAL_HOT void bal_engine_stop_thread(bal_engine_t *engine); + /// Resets `engine` for the next compilation unit. This is a low-cost memory /// operation designed to be called between translation units. /// diff --git a/src/bal_engine.c b/src/bal_engine.c index ccd93be8..b19a4240 100644 --- a/src/bal_engine.c +++ b/src/bal_engine.c @@ -448,6 +448,25 @@ bal_engine_run_thread(bal_engine_t *engine) return engine->status; } +void +bal_engine_stop_thread(bal_engine_t *BAL_RESTRICT engine) +{ + if (BAL_UNLIKELY(NULL == engine)) + { + return; + } + + if (BAL_UNLIKELY(NULL == engine->engine_state)) + { + BAL_LOG_ERROR(&engine->logger, "Aborting function: engine state is NULL"); + engine->status = BAL_ERROR_INVALID_ARGUMENT; + return; + } + + internal_engine_state_t *BAL_RESTRICT engine_state = engine->engine_state; + atomic_store_explicit(&engine_state->thread_state.stop_requested, true, memory_order_release); +} + bal_error_t bal_engine_reset(bal_engine_t *BAL_RESTRICT engine) {