blob: 1b88016311f66bd4810552b7db34c7259d54720d [file] [log] [blame]
/*
* Copyright (c) 2021, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for `Heap::Allocatable`.
*/
#ifndef HEAP_ALLOCATABLE_HPP_
#define HEAP_ALLOCATABLE_HPP_
#include "openthread-core-config.h"
#include "common/code_utils.hpp"
#include "common/error.hpp"
#include "common/heap.hpp"
#include "common/new.hpp"
namespace ot {
namespace Heap {
/**
* This template class defines a `Heap::Allocatable` object.
*
* `Heap::Allocatable` provides methods to allocate and free instances of `Type` on heap.
*
* Users of this class should follow CRTP-style inheritance, i.e., the `Type` class itself should inherit from
* `Allocatable<Type>`.
*
* The `Type` class destructor is used when `Free()` is called. The destructor frees any heap allocated data members
* that are stored in a `Type` instance (e.g., `Heap::String`, `Heap::Data`, etc).
*
*/
template <class Type> class Allocatable
{
public:
/**
* This static method allocates a new instance of `Type` on heap and initializes it using `Type` constructor.
*
* The `Type` class MUST have a constructor `Type(Args...)` which is invoked upon allocation of new `Type` to
* initialize it.
*
* @param[in] aArgs A set of arguments to pass to the `Type` constructor of the allocated `Type` instance.
*
* @returns A pointer to the newly allocated instance or `nullptr` if it fails to allocate.
*
*/
template <typename... Args> static Type *Allocate(Args &&... aArgs)
{
void *buf = Heap::CAlloc(1, sizeof(Type));
return (buf != nullptr) ? new (buf) Type(static_cast<Args &&>(aArgs)...) : nullptr;
}
/**
* This static method allocates a new instance of `Type` on heap and initializes it using `Type::Init()` method.
*
* The `Type` class MUST have a default constructor (with no arguments) which is invoked upon allocation of new
* `Type` instance. It MUST also provide an `Error Init(Args...)` method to initialize the instance. If any `Error`
* other than `kErrorNone` is returned the initialization is considered failed.
*
* @param[in] aArgs A set of arguments to initialize the allocated `Type` instance.
*
* @returns A pointer to the newly allocated instance or `nullptr` if it fails to allocate or initialize.
*
*/
template <typename... Args> static Type *AllocateAndInit(Args &&... aArgs)
{
void *buf = Heap::CAlloc(1, sizeof(Type));
Type *object = nullptr;
VerifyOrExit(buf != nullptr);
object = new (buf) Type();
if (object->Init(static_cast<Args &&>(aArgs)...) != kErrorNone)
{
object->Free();
object = nullptr;
}
exit:
return object;
}
/**
* This method frees the `Type` instance.
*
* The instance MUST be heap allocated using either `Allocate()` or `AllocateAndInit()`.
*
* The `Free()` method invokes the `Type` destructor before releasing the allocated heap buffer for the instance.
* This ensures that any heap allocated member variables in `Type` are freed before the `Type` instance itself is
* freed.
*
*/
void Free(void)
{
static_cast<Type *>(this)->~Type();
Heap::Free(this);
}
protected:
Allocatable(void) = default;
};
} // namespace Heap
} // namespace ot
#endif // HEAP_ALLOCATABLE_HPP_