diff --git a/src/core/common/callback.hpp b/src/core/common/callback.hpp index f4162203e..da4a6fa27 100644 --- a/src/core/common/callback.hpp +++ b/src/core/common/callback.hpp @@ -206,6 +206,25 @@ public: Invoke(static_cast(aArgs)...); } } + + /** + * Invokes the callback handler if it is set and clears it. + * + * The method MUST be used when the handler function returns `void`. + * + * The callback is cleared first before invoking its handler to allow it to be set again from the handler + * implementation. + * + * @param[in] aArgs The args to pass to the callback handler. + * + */ + template void InvokeAndClearIfSet(Args &&...aArgs) + { + Callback callbackCopy = *this; + + CallbackBase::Clear(); + callbackCopy.InvokeIfSet(static_cast(aArgs)...); + } }; // Specialization for `kContextAsFirstArg` @@ -236,6 +255,25 @@ public: Invoke(static_cast(aArgs)...); } } + + /** + * Invokes the callback handler if it is set and clears it. + * + * The method MUST be used when the handler function returns `void`. + * + * The callback is cleared first before invoking its handler to allow it to be set again from the handler + * implementation. + * + * @param[in] aArgs The args to pass to the callback handler. + * + */ + template void InvokeAndClearIfSet(Args &&...aArgs) + { + Callback callbackCopy = *this; + + CallbackBase::Clear(); + callbackCopy.InvokeIfSet(static_cast(aArgs)...); + } }; } // namespace ot diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp index ef4cfcd45..05d103638 100644 --- a/src/core/meshcop/dataset_manager.cpp +++ b/src/core/meshcop/dataset_manager.cpp @@ -323,6 +323,7 @@ void DatasetManager::HandleMgmtSetResponse(Coap::Message *aMessage, const Ip6::M SuccessOrExit(error = aError); VerifyOrExit(Tlv::Find(*aMessage, state) == kErrorNone && state != StateTlv::kPending, error = kErrorParse); + if (state == StateTlv::kReject) { error = kErrorRejected; @@ -333,13 +334,7 @@ exit: mMgmtPending = false; - if (mMgmtSetCallback.IsSet()) - { - Callback callbackCopy = mMgmtSetCallback; - - mMgmtSetCallback.Clear(); - callbackCopy.Invoke(error); - } + mMgmtSetCallback.InvokeAndClearIfSet(error); mTimer.Start(kSendSetDelay); } diff --git a/src/core/thread/anycast_locator.cpp b/src/core/thread/anycast_locator.cpp index 14e0fd843..f3fd31e90 100644 --- a/src/core/thread/anycast_locator.cpp +++ b/src/core/thread/anycast_locator.cpp @@ -109,13 +109,7 @@ void AnycastLocator::HandleResponse(Coap::Message *aMessage, const Ip6::MessageI address = &meshLocalAddress; exit: - if (mCallback.IsSet()) - { - Callback callbackCopy = mCallback; - - mCallback.Clear(); - callbackCopy.Invoke(aError, address, rloc16); - } + mCallback.InvokeAndClearIfSet(aError, address, rloc16); } #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_SEND_RESPONSE diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 85e0039c8..903735444 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -253,14 +253,7 @@ void Mle::Stop(StopMode aMode) exit: mDetachGracefullyTimer.Stop(); - - if (mDetachGracefullyCallback.IsSet()) - { - Callback callbackCopy = mDetachGracefullyCallback; - - mDetachGracefullyCallback.Clear(); - callbackCopy.Invoke(); - } + mDetachGracefullyCallback.InvokeAndClearIfSet(); } void Mle::ResetCounters(void) diff --git a/src/core/thread/mlr_manager.cpp b/src/core/thread/mlr_manager.cpp index dd25d7bea..df770fe4f 100644 --- a/src/core/thread/mlr_manager.cpp +++ b/src/core/thread/mlr_manager.cpp @@ -344,17 +344,15 @@ void MlrManager::HandleRegisterResponse(otMessage *aMessage, const otMessageInfo { OT_UNUSED_VARIABLE(aMessageInfo); - uint8_t status; - Error error; - AddressArray failedAddresses; - Callback callbackCopy = mRegisterCallback; + uint8_t status; + Error error; + AddressArray failedAddresses; mRegisterPending = false; - mRegisterCallback.Clear(); error = ParseMlrResponse(aResult, AsCoapMessagePtr(aMessage), status, failedAddresses); - callbackCopy.InvokeIfSet(error, status, failedAddresses.GetArrayBuffer(), failedAddresses.GetLength()); + mRegisterCallback.InvokeAndClearIfSet(error, status, failedAddresses.GetArrayBuffer(), failedAddresses.GetLength()); } #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE