cmvr_head/packages/erpc-1.14.0/erpc_c/infra/erpc_manually_constructed.hpp
2025-12-30 15:44:41 +08:00

239 lines
7.8 KiB
C++

/*
* Copyright (c) 2014, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
* Copyright 2021 ACRIOS Systems s.r.o.
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _EMBEDDED_RPC__MANUALLY_CONSTRUCTED_H_
#define _EMBEDDED_RPC__MANUALLY_CONSTRUCTED_H_
#include "erpc_config_internal.h"
#include <new>
#include <stdint.h>
/*!
* @addtogroup infra_utility
* @{
* @file
*/
////////////////////////////////////////////////////////////////////////////////
// Classes
////////////////////////////////////////////////////////////////////////////////
namespace erpc {
/*!
* @brief Allocates static storage for an object.
*
* This template class defines storage of the template class' size. Then it
* gives the user explicit control over construction and destruction of the
* object residing in that storage. This is useful for placing objects in
* unions, or other situations where you need static storage but want to delay
* the actual construction of the object.
*
* Objects of this class will act as a pointer to the template argument class
* type. Of course, if the object has not yet been constructed then the
* behavior is undefined if the pointer to it is used.
*
* Note that there is not a constructor or deconstructor. This is because
* members of unions cannot have constructors or deconstructors.
*
* Instances of this template class are aligned to 8 bytes.
*
* @ingroup infra_utility
*/
template <class T>
class ManuallyConstructed
{
public:
//! @name Object access
//@{
T *get(void) { return (m_isConstructed) ? reinterpret_cast<T *>(&m_storage) : nullptr; }
const T *get(void) const { return (m_isConstructed) ? reinterpret_cast<const T *>(&m_storage) : nullptr; }
T *operator->(void) { return get(); }
const T *operator->(void) const { return get(); }
T &operator*(void)
{
if (m_isConstructed)
{
return *get();
}
else
{
memset(&m_storage, 0, sizeof(m_storage) * 8);
return reinterpret_cast<T &>(m_storage);
};
}
const T &operator*(void) const
{
if (m_isConstructed)
{
return *get();
}
else
{
memset(&m_storage, 0, sizeof(m_storage) * 8);
return reinterpret_cast<const T &>(m_storage);
};
}
operator T *(void) { return get(); }
operator const T *(void) const { return get(); }
//@}
//! @name Explicit construction methods
//@{
void construct(void)
{
destroy();
new (m_storage) T;
m_isConstructed = true;
}
template <typename A1>
void construct(const A1 &a1)
{
destroy();
new (m_storage) T(a1);
m_isConstructed = true;
}
template <typename A1, typename A2>
void construct(const A1 &a1, const A2 &a2)
{
destroy();
new (m_storage) T(a1, a2);
m_isConstructed = true;
}
template <typename A1, typename A2, typename A3>
void construct(const A1 &a1, const A2 &a2, const A3 &a3)
{
destroy();
new (m_storage) T(a1, a2, a3);
m_isConstructed = true;
}
template <typename A1, typename A2, typename A3, typename A4>
void construct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
{
destroy();
new (m_storage) T(a1, a2, a3, a4);
m_isConstructed = true;
}
template <typename A1, typename A2, typename A3, typename A4, typename A5>
void construct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5)
{
destroy();
new (m_storage) T(a1, a2, a3, a4, a5);
m_isConstructed = true;
}
template <typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
void construct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6)
{
destroy();
new (m_storage) T(a1, a2, a3, a4, a5, a6);
m_isConstructed = true;
}
//@}
/*!
* @brief Invoke the object's destructor.
*
* Behavior is undefined if the objected was not previously initialized.
*/
void destroy(void)
{
if (m_isConstructed)
{
get()->~T();
m_isConstructed = false;
}
}
/*!
* @brief Returns information if object is free or is used.
*
* @return true Object is constructed and used.
* @return false Object wasn't constructed or it was destructed already.
*/
bool isUsed(void) { return m_isConstructed; }
protected:
/*!
* @brief Storage for the object.
*
* An array of uint64 is used to get 8-byte alignment.
*/
uint64_t m_storage[(sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t)];
/*!
* @brief Track construct/destruct calls.
*
* Based on this variable we can allow or forbid construct/destruct calls.
*/
bool m_isConstructed = false;
};
#define ERPC_MANUALLY_CONSTRUCTED(class, variableName) static ManuallyConstructed<class> variableName
#define ERPC_MANUALLY_CONSTRUCTED_ARRAY(class, variableName, dimension) \
ERPC_MANUALLY_CONSTRUCTED(class, variableName)[dimension]
#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC
#define ERPC_MANUALLY_CONSTRUCTED_STATIC(class, variableName) ERPC_MANUALLY_CONSTRUCTED(class, variableName)
#else
#define ERPC_MANUALLY_CONSTRUCTED_STATIC(class, variableName)
#endif
#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC
#define ERPC_MANUALLY_CONSTRUCTED_ARRAY_STATIC(class, variableName, dimension) \
ERPC_MANUALLY_CONSTRUCTED_ARRAY(class, variableName, dimension)
#else
#define ERPC_MANUALLY_CONSTRUCTED_ARRAY_STATIC(class, variableName, dimension)
#endif
#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC
#define ERPC_CREATE_NEW_OBJECT(class, arrayOfObjects, numberOfObjects, ...) \
return new (std::nothrow) class(__VA_ARGS__);
#define ERPC_DESTROY_OBJECT(object, ...) delete object;
#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC
#define ERPC_CREATE_NEW_OBJECT(class, arrayOfObjects, numberOfObjects, ...) \
uint8_t objectsIterator; \
class *ret = NULL; \
for (objectsIterator = 0; objectsIterator < numberOfObjects; objectsIterator++) \
{ \
if (!arrayOfObjects[objectsIterator].isUsed()) \
{ \
arrayOfObjects[objectsIterator].construct(__VA_ARGS__); \
ret = arrayOfObjects[objectsIterator].get(); \
break; \
} \
} \
return ret;
#define ERPC_DESTROY_OBJECT(object, arrayOfObjects, numberOfObjects) \
uint8_t objectsIterator; \
for (objectsIterator = 0; objectsIterator < numberOfObjects; objectsIterator++) \
{ \
if (object == arrayOfObjects[objectsIterator].get()) \
{ \
arrayOfObjects[objectsIterator].destroy(); \
break; \
} \
}
#endif
} // namespace erpc
/*! @} */
#endif // _EMBEDDED_RPC__MANUALLY_CONSTRUCTED_H_