/* * 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 { /** * 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`. * * 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 Allocatable { public: /** * 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 static Type *Allocate(Args &&...aArgs) { void *buf = Heap::CAlloc(1, sizeof(Type)); return (buf != nullptr) ? new (buf) Type(static_cast(aArgs)...) : nullptr; } /** * 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 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(aArgs)...) != kErrorNone) { object->Free(); object = nullptr; } exit: return object; } /** * 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(this)->~Type(); Heap::Free(this); } protected: Allocatable(void) = default; }; } // namespace Heap } // namespace ot #endif // HEAP_ALLOCATABLE_HPP_