From ca45026ba5b02bc4bc3f668b13724c124a3997cb Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 26 Apr 2024 11:39:58 -0700 Subject: [PATCH] [callback] add `InvokeAndClearIfSet()` helper (#10064) Will first clear the callback before invoking its handler so to allow the callback to possibly set again from the handler implementation. --- src/core/common/callback.hpp | 38 ++++++++++++++++++++++++++++ src/core/meshcop/dataset_manager.cpp | 9 ++----- src/core/thread/anycast_locator.cpp | 8 +----- src/core/thread/mle.cpp | 9 +------ src/core/thread/mlr_manager.cpp | 10 +++----- 5 files changed, 46 insertions(+), 28 deletions(-) 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