esp-idf/components/nvs_flash/src/nvs_memory_management.hpp

63 lines
2.2 KiB
C++
Raw Normal View History

/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <cstdlib>
#pragma once
/**
* @brief Type that is only usable with new (std::nothrow) to avoid exceptions.
*
* This struct shall be inherited by all types in NVS that may be allocated dynamically (with new).
*
* NVS allocates memory at runtime. Because we use C++, we need to avoid the global ``operator new`` from libstdc++,
* since it throws exceptions and we compile NVS with ``-fno-exceptions``. We also need to avoid the global
* non-throwing version of that operator from libstdc++, since it is merely a wrapper around the original operator
* catching all exceptions.
*
* This struct removes the normal operator new from this and all types inheriting from it. It furthermore provides
* a custom version of operator new (..., const std::nothrow_t&) noexcept that will not use C++ exceptions.
*
* E.g., if you have a type MyType inheriting from ExceptionlessAllocatable, you want to use it as follows:
* @code{c++}
* MyType : public ExceptionlessAllocatable {
* ExceptionlessAllocatable();
* ExceptionlessAllocatable(int param);
* };
* // ...
* MyType *m0 = new (std::nothrow) MyType;
* MyType *m1 = new (std::nothrow) MyType(47);
* // ...
* delete m1;
* delete m0;
* @endcode
*/
struct ExceptionlessAllocatable {
/**
* Disallow use of the default new operator, all of NVS is currently tailored to not throw exceptions
*/
static void *operator new( std::size_t ) = delete;
/**
* Simple implementation with malloc(). No exceptions are thrown if the allocation fails.
* To use this operator, your type must inherit from this class and then allocate with:
* @code{c}
* new (std::nothrow) <YourType>; // default constructor
* new (std::nothrow) <YourType>(<constructor parameters>); // non-default constructor
* @endcode
*/
void *operator new (size_t size, const std::nothrow_t&) noexcept {
return std::malloc(size);
}
/**
* Use \c delete as normal. This operator will be called automatically instead of the global one from libstdc++.
*/
void operator delete (void *obj) noexcept {
free(obj);
}
};