#ifndef PMEMOBJ_MAKE_PERSISTENT_ARRAY_HPP
#define PMEMOBJ_MAKE_PERSISTENT_ARRAY_HPP
#include "libpmemobj++/detail/array_traits.hpp"
#include "libpmemobj++/detail/check_persistent_ptr_array.hpp"
#include "libpmemobj++/detail/common.hpp"
#include "libpmemobj++/detail/life.hpp"
#include "libpmemobj++/detail/pexceptions.hpp"
#include "libpmemobj/tx_base.h"
namespace pmem
{
namespace obj
{
template <typename T>
typename detail::pp_if_array<T>::type
make_persistent(std::size_t N)
{
typedef typename detail::pp_array_type<T>::type I;
if (pmemobj_tx_stage() != TX_STAGE_WORK)
throw transaction_scope_error(
"refusing to allocate "
"memory outside of transaction scope");
persistent_ptr<T> ptr =
pmemobj_tx_alloc(sizeof(I) * N, detail::type_num<I>());
if (ptr == nullptr)
throw transaction_alloc_error("failed to allocate "
"persistent memory array");
std::size_t i;
try {
for (i = 0; i < N; ++i)
detail::create<I>(ptr.get() + i);
} catch (...) {
for (std::size_t j = 1; j <= i; ++j)
detail::destroy<I>(ptr[i - j]);
pmemobj_tx_free(*ptr.raw_ptr());
throw;
}
return ptr;
}
template <typename T>
typename detail::pp_if_size_array<T>::type
make_persistent()
{
typedef typename detail::pp_array_type<T>::type I;
enum { N = detail::pp_array_elems<T>::elems };
if (pmemobj_tx_stage() != TX_STAGE_WORK)
throw transaction_scope_error(
"refusing to allocate "
"memory outside of transaction scope");
persistent_ptr<T> ptr =
pmemobj_tx_alloc(sizeof(I) * N, detail::type_num<I>());
if (ptr == nullptr)
throw transaction_alloc_error("failed to allocate "
"persistent memory array");
std::size_t i;
try {
for (i = 0; i < N; ++i)
detail::create<I>(ptr.get() + i);
} catch (...) {
for (std::size_t j = 1; j <= i; ++j)
detail::destroy<I>(ptr[i - j]);
pmemobj_tx_free(*ptr.raw_ptr());
throw;
}
return ptr;
}
template <typename T>
void
delete_persistent(typename detail::pp_if_array<T>::type ptr, std::size_t N)
{
typedef typename detail::pp_array_type<T>::type I;
if (pmemobj_tx_stage() != TX_STAGE_WORK)
throw transaction_scope_error(
"refusing to free "
"memory outside of transaction scope");
if (ptr == nullptr)
return;
for (std::size_t i = 0; i < N; ++i)
detail::destroy<I>(ptr[N - 1 - i]);
if (pmemobj_tx_free(*ptr.raw_ptr()) != 0)
throw transaction_free_error("failed to delete "
"persistent memory object");
}
template <typename T>
void
delete_persistent(typename detail::pp_if_size_array<T>::type ptr)
{
typedef typename detail::pp_array_type<T>::type I;
enum { N = detail::pp_array_elems<T>::elems };
if (pmemobj_tx_stage() != TX_STAGE_WORK)
throw transaction_scope_error(
"refusing to free "
"memory outside of transaction scope");
if (ptr == nullptr)
return;
for (std::size_t i = 0; i < N; ++i)
detail::destroy<I>(ptr[N - 1 - i]);
if (pmemobj_tx_free(*ptr.raw_ptr()) != 0)
throw transaction_free_error("failed to delete "
"persistent memory object");
}
}
}
#endif