#ifndef NOTIFIER_HPP_
#define NOTIFIER_HPP_
#include "openthread-core-config.h"
#include <stdbool.h>
#include <stdint.h>
#include <openthread/instance.h>
#include <openthread/platform/toolchain.h>
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/tasklet.hpp"
namespace ot {
class Notifier : public InstanceLocator, private NonCopyable
{
public:
class Callback : public OwnerLocator, public LinkedListEntry<Callback>
{
friend class Notifier;
friend class LinkedListEntry<Callback>;
public:
typedef void (*Handler)(Callback &aCallback, otChangedFlags aFlags);
Callback(Instance &aInstance, Handler aHandler, void *aOwner);
private:
void Invoke(otChangedFlags aFlags) { mHandler(*this, aFlags); }
Handler mHandler;
Callback *mNext;
};
explicit Notifier(Instance &aInstance);
otError RegisterCallback(otStateChangedCallback aCallback, void *aContext);
void RemoveCallback(otStateChangedCallback aCallback, void *aContext);
void Signal(otChangedFlags aFlags);
void SignalIfFirst(otChangedFlags aFlags);
bool IsPending(void) const { return (mFlagsToSignal != 0); }
bool HasSignaled(otChangedFlags aFlags) const { return (mSignaledFlags & aFlags) == aFlags; }
template <typename Type> otError Update(Type &aVariable, const Type &aNewValue, otChangedFlags aFlags)
{
otError error = OT_ERROR_NONE;
if (aVariable == aNewValue)
{
SignalIfFirst(aFlags);
error = OT_ERROR_ALREADY;
}
else
{
aVariable = aNewValue;
Signal(aFlags);
}
return error;
}
private:
enum
{
kMaxExternalHandlers = OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS,
kFlagsStringLineLimit = 70, kMaxFlagNameLength = 25, kFlagsStringBufferSize = kFlagsStringLineLimit + kMaxFlagNameLength,
};
struct ExternalCallback
{
otStateChangedCallback mHandler;
void * mContext;
};
void RegisterCallback(Callback &aCallback);
static void HandleStateChanged(Tasklet &aTasklet);
void HandleStateChanged(void);
void LogChangedFlags(otChangedFlags aFlags) const;
const char *FlagToString(otChangedFlags aFlag) const;
otChangedFlags mFlagsToSignal;
otChangedFlags mSignaledFlags;
Tasklet mTask;
LinkedList<Callback> mCallbacks;
ExternalCallback mExternalCallbacks[kMaxExternalHandlers];
};
}
#endif