[locator] add GetProvider base to provide Get<Type>() on Message (#7679)

This commit introduces a base class `GetProvider` which provides
`Get<Type>()` methods using `GetInstance()` (which is expected to be
provided by the derived class in a CRTP style inheritance). The class
`GetProvider` is used as base class of `InstanceLocator`.

This model allows us to provide `Get<Type>()` methods on types that
may not be directly an `InstanceLocator`. For example, this commit
uses this model on `Message` class. `Message` always retains the
`MessagePool` which can be used to get to the `Instance` that owns
the `Message`. Note that it is not straight-forward to to have
`Message` directly inherit from `InstanceLocator` (due to way
`Message` is built from `Buffer` and uses `Metadata` header and that
`InstanceLocator` behaves differently under single vs multi instance
configs).
This commit is contained in:
Abtin Keshavarzian
2022-05-12 09:59:14 -07:00
committed by GitHub
parent c2dd7eb66d
commit 8085f0a4ac
4 changed files with 56 additions and 33 deletions
+5
View File
@@ -430,6 +430,11 @@ DefineCoreType(otBufferInfo, Instance::BufferInfo);
// Specializations of the `Get<Type>()` method.
template <> inline Instance &Instance::Get(void)
{
return *this;
}
template <> inline Radio &Instance::Get(void)
{
return mRadio;
+33 -14
View File
@@ -58,6 +58,38 @@ extern uint64_t gInstanceRaw[];
*
*/
/**
* This template class implements `Get<Type>()` method for different `Type` objects belonging to the OpenThread
* instance.
*
* Users of this class MUST follow CRTP-style inheritance, i.e., the class `Class` itself should publicly inherit
* from `GetProvider<Class>`.
*
* @tparam InstanceGetProvider The template sub-lass used in CRTP style inheritance.
* `InstanceGetProvider` MUST provide a method with the following signature:
* `Instance &GetInstance(void) const`
*
*/
template <class InstanceGetProvider> class GetProvider
{
public:
/**
* This template method returns a reference to a given `Type` object belonging to the OpenThread instance.
*
* For example, `Get<MeshForwarder>()` returns a reference to the `MeshForwarder` object of the instance.
*
* Note that any `Type` for which the `Get<Type>` is defined MUST be uniquely accessible from the OpenThread
* `Instance` through the member variable property hierarchy.
*
* @returns A reference to the `Type` object of the instance.
*
*/
template <typename Type> inline Type &Get(void) const; // Implemented in `locator_getters.hpp`.
protected:
GetProvider(void) = default;
};
/**
* This class implements a locator for an OpenThread Instance object.
*
@@ -69,7 +101,7 @@ extern uint64_t gInstanceRaw[];
* single-instance case, this class becomes an empty base class.
*
*/
class InstanceLocator
class InstanceLocator : public GetProvider<InstanceLocator>
{
friend class InstanceLocatorInit;
@@ -86,19 +118,6 @@ public:
Instance &GetInstance(void) const { return *reinterpret_cast<Instance *>(&gInstanceRaw); }
#endif
/**
* This template method returns a reference to a given `Type` object belonging to the OpenThread instance.
*
* For example, `Get<MeshForwarder>()` returns a reference to the `MeshForwarder` object of the instance.
*
* Note that any `Type` for which the `Get<Type>` is defined MUST be uniquely accessible from the OpenThread
* `Instance` through the member variable property hierarchy.
*
* @returns A reference to the `Type` object of the instance.
*
*/
template <typename Type> inline Type &Get(void) const; // Implemented in `locator_getters.hpp`.
protected:
/**
* This constructor initializes the object.
+4 -18
View File
@@ -42,25 +42,11 @@
namespace ot {
/**
* This method returns a reference to the parent OpenThread Instance.
*
* This definition is a specialization of template `Get<Type>` for `Get<Instance>()`,
*
* @returns A reference to `Instance` object.
*
*/
template <> inline Instance &InstanceLocator::Get(void) const
template <typename InstanceGetProvider>
template <typename Type>
inline Type &GetProvider<InstanceGetProvider>::Get(void) const
{
return GetInstance();
}
template <typename Type> inline Type &InstanceLocator::Get(void) const
{
// This method uses the `Instance` template method `Get<Type>`
// to get to the given `Type` from the single OpenThread
// instance.
return GetInstance().Get<Type>();
return static_cast<const InstanceGetProvider *>(this)->GetInstance().template Get<Type>();
}
} // namespace ot
+14 -1
View File
@@ -258,7 +258,7 @@ static_assert(sizeof(Buffer) >= kBufferSize, "Buffer size if not valid");
* This class represents a message.
*
*/
class Message : public otMessage, public Buffer
class Message : public otMessage, public Buffer, public GetProvider<Message>
{
friend class Checksum;
friend class Crypto::HmacSha256;
@@ -410,6 +410,14 @@ public:
static const otMessageSettings kDefault;
};
/**
* This method returns a reference to the OpenThread Instance which owns the `Message`.
*
* @returns A reference to the `Instance`.
*
*/
Instance &GetInstance(void) const;
/**
* This method frees this message buffer.
*
@@ -1663,6 +1671,11 @@ private:
#endif
};
inline Instance &Message::GetInstance(void) const
{
return GetMessagePool()->GetInstance();
}
/**
* @}
*