From 2dce461b25a11c4adb7b4cd0b3e6b1eb3da83fda Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Sun, 10 Nov 2024 20:05:24 -0800 Subject: [PATCH] [notifier] use `Array` to track external callbacks (#10907) This commit simplifies `Notifier` by using `Array` to track registered callbacks. --- src/core/common/callback.hpp | 13 +++++++++++ src/core/common/notifier.cpp | 44 ++++++++---------------------------- src/core/common/notifier.hpp | 38 ++++++++++++++++++------------- 3 files changed, 45 insertions(+), 50 deletions(-) diff --git a/src/core/common/callback.hpp b/src/core/common/callback.hpp index 77136bda5..1da26be76 100644 --- a/src/core/common/callback.hpp +++ b/src/core/common/callback.hpp @@ -112,6 +112,19 @@ public: return (mHandler == aHandler) && (mContext == aContext); } + /** + * Overloads operator `==` to evaluate whether or not two given `Callback` objects are equal. + * + * @param[in] aOtherCallback The callback to compare with. + * + * @retval TRUE The two callbacks are equal. + * @retval FALSE The two callbacks are not equal. + */ + bool operator==(const CallbackBase &aOtherCallback) const + { + return Matches(aOtherCallback.mHandler, aOtherCallback.mContext); + } + protected: CallbackBase(void) : mHandler(nullptr) diff --git a/src/core/common/notifier.cpp b/src/core/common/notifier.cpp index f944f7898..f59caace1 100644 --- a/src/core/common/notifier.cpp +++ b/src/core/common/notifier.cpp @@ -43,51 +43,27 @@ Notifier::Notifier(Instance &aInstance) : InstanceLocator(aInstance) , mTask(aInstance) { - for (ExternalCallback &callback : mExternalCallbacks) - { - callback.Clear(); - } } -Error Notifier::RegisterCallback(otStateChangedCallback aCallback, void *aContext) +Error Notifier::RegisterCallback(StateChangedCallback aCallback, void *aContext) { - Error error = kErrorNone; - ExternalCallback *unusedCallback = nullptr; + Error error = kErrorNone; + ExternalCallback newCallback; - VerifyOrExit(aCallback != nullptr); - - for (ExternalCallback &callback : mExternalCallbacks) - { - VerifyOrExit(!callback.Matches(aCallback, aContext), error = kErrorAlready); - - if (!callback.IsSet() && (unusedCallback == nullptr)) - { - unusedCallback = &callback; - } - } - - VerifyOrExit(unusedCallback != nullptr, error = kErrorNoBufs); - - unusedCallback->Set(aCallback, aContext); + newCallback.Set(aCallback, aContext); + VerifyOrExit(!mExternalCallbacks.Contains(newCallback), error = kErrorAlready); + error = mExternalCallbacks.PushBack(newCallback); exit: return error; } -void Notifier::RemoveCallback(otStateChangedCallback aCallback, void *aContext) +void Notifier::RemoveCallback(StateChangedCallback aCallback, void *aContext) { - VerifyOrExit(aCallback != nullptr); + ExternalCallback callbackToRemove; - for (ExternalCallback &callback : mExternalCallbacks) - { - if (callback.Matches(aCallback, aContext)) - { - callback.Clear(); - } - } - -exit: - return; + callbackToRemove.Set(aCallback, aContext); + mExternalCallbacks.Remove(callbackToRemove); } void Notifier::Signal(Event aEvent) diff --git a/src/core/common/notifier.hpp b/src/core/common/notifier.hpp index b2fc7a30e..8a9337695 100644 --- a/src/core/common/notifier.hpp +++ b/src/core/common/notifier.hpp @@ -42,6 +42,7 @@ #include #include +#include "common/array.hpp" #include "common/callback.hpp" #include "common/error.hpp" #include "common/locator.hpp" @@ -179,14 +180,17 @@ private: * * For core internal modules, `Notifier` class emits events directly to them by invoking method `HandleNotifierEvents()` * on the module instance. - * - * A `otStateChangedCallback` callback can be explicitly registered with the `Notifier`. This is mainly intended for use - * by external users (i.e.provided as an OpenThread public API). Max number of such callbacks that can be registered at - * the same time is specified by `OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS` configuration parameter. */ class Notifier : public InstanceLocator, private NonCopyable { public: + /** + * Maximum number of external callback handlers that can be registered. + */ + static constexpr uint16_t kMaxExternalHandlers = OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS; + + typedef otStateChangedCallback StateChangedCallback; ///< State changed callback + /** * Initializes a `Notifier` instance. * @@ -195,7 +199,10 @@ public: explicit Notifier(Instance &aInstance); /** - * Registers an `otStateChangedCallback` handler. + * Registers an external `StateChangedCallback`. + * + * This is intended for use by external users (i.e., provided as an OpenThread public API). `kMaxExternalHandlers` + * specifies the maximum number of callbacks. * * @param[in] aCallback A pointer to the handler function that is called to notify of the changes. * @param[in] aContext A pointer to arbitrary context information. @@ -204,15 +211,15 @@ public: * @retval kErrorAlready The callback was already registered. * @retval kErrorNoBufs Could not add the callback due to resource constraints. */ - Error RegisterCallback(otStateChangedCallback aCallback, void *aContext); + Error RegisterCallback(StateChangedCallback aCallback, void *aContext); /** - * Removes/unregisters a previously registered `otStateChangedCallback` handler. + * Removes/unregisters a previously registered `StateChangedCallback` handler. * * @param[in] aCallback A pointer to the callback function pointer. * @param[in] aContext A pointer to arbitrary context information. */ - void RemoveCallback(otStateChangedCallback aCallback, void *aContext); + void RemoveCallback(StateChangedCallback aCallback, void *aContext); /** * Schedules signaling of an event. @@ -279,8 +286,6 @@ public: } private: - static constexpr uint16_t kMaxExternalHandlers = OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS; - // Character limit to divide the log into multiple lines in `LogChangedFlags()`. static constexpr uint16_t kFlagsStringLineLimit = 70; @@ -289,19 +294,20 @@ private: static constexpr uint16_t kFlagsStringBufferSize = kFlagsStringLineLimit + kMaxFlagNameLength; - typedef Callback ExternalCallback; + typedef Callback ExternalCallback; void EmitEvents(void); void LogEvents(Events aEvents) const; const char *EventToString(Event aEvent) const; - using EmitEventsTask = TaskletIn; + using EmitEventsTask = TaskletIn; + using ExternalCallbackArray = Array; - Events mEventsToSignal; - Events mSignaledEvents; - EmitEventsTask mTask; - ExternalCallback mExternalCallbacks[kMaxExternalHandlers]; + Events mEventsToSignal; + Events mSignaledEvents; + EmitEventsTask mTask; + ExternalCallbackArray mExternalCallbacks; }; /**