Skip to content

Commit

Permalink
update uninitialized
Browse files Browse the repository at this point in the history
  • Loading branch information
wjr-z committed Aug 7, 2024
1 parent 6e98d7d commit c5b426e
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 233 deletions.
10 changes: 3 additions & 7 deletions include/wjr/biginteger/biginteger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3131,7 +3131,6 @@ template <typename S, typename Engine,
WJR_REQUIRES_I(biginteger_uniform_random_bit_generator_v<Engine>)>
void __urandom_impl(basic_biginteger<S> *dst, const biginteger_data *limit,
Engine &engine) noexcept {
std::optional<uninitialized<math_detail::unique_stack_alloc>> stkal;
uint32_t size = limit->size();

WJR_ASSERT(size != 0);
Expand All @@ -3151,9 +3150,10 @@ void __urandom_impl(basic_biginteger<S> *dst, const biginteger_data *limit,
const auto dp = dst->data();
const uint64_t *lp = limit->data();

math_detail::unique_stack_alloc stkal(math_detail::stack_alloc);

if (__equal_pointer(dst, limit)) {
stkal.emplace(math_detail::stack_alloc);
const auto tp = (uint64_t *)(*stkal)->allocate(size * sizeof(uint64_t));
const auto tp = static_cast<uint64_t *>(stkal.allocate(size * sizeof(uint64_t)));
std::copy_n(lp, size, tp);
lp = tp;
}
Expand Down Expand Up @@ -3198,10 +3198,6 @@ void __urandom_impl(basic_biginteger<S> *dst, const biginteger_data *limit,

size = normalize(dp, size);
dst->set_ssize(size);

if (stkal.has_value()) {
stkal->reset();
}
}

template <typename S, typename Engine,
Expand Down
2 changes: 0 additions & 2 deletions include/wjr/expected.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,8 +704,6 @@ class WJR_EMPTY_BASES expected
using error_type = typename Mybase::error_type;
using unexpected_type = unexpected<error_type>;

using Mybase::Mybase;

expected() = default;
expected(const expected &) = default;
expected(expected &&) = default;
Expand Down
47 changes: 43 additions & 4 deletions include/wjr/json/document.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,48 @@
#ifndef WJR_JSON_DOCUMENT_HPP__
#define WJR_JSON_DOCUMENT_HPP__

#include <wjr/format/charconv.hpp>
#include <wjr/json/parser.hpp>
#include <map>

namespace wjr::json {} // namespace wjr::json
#include <wjr/json/visitor.hpp>

#endif // WJR_JSON_DOCUMENT_HPP__
namespace wjr::json {

template <typename Traits>
class basic_json;

template <typename Traits>
struct get_relocate_mode<basic_json<Traits>> {
static constexpr relocate_t value = relocate_t::trivial;
};

template <template <typename Char, typename Traits, typename Alloc> typename String,
template <typename Key, typename Ty, typename Pr, typename Alloc>
typename Object,
template <typename T, typename Alloc> typename Array,
template <typename T> typename Allocator>
struct basic_json_traits {
private:
using json_type = basic_json<basic_json_traits>;

public:
using string_type = String<char, std::char_traits<char>, Allocator<char>>;
using object_type = Object<string_type, json_type, std::less<string_type>,
Allocator<std::pair<const string_type, json_type>>>;
using array_type = Array<json_type, Allocator<json_type>>;
};

using default_json_traits =
basic_json_traits<std::basic_string, std::map, vector, memory_pool>;
using __default_json_string = typename json::default_json_traits::string_type;

template <typename Traits>
class basic_json {};

} // namespace wjr::json

namespace wjr {
WJR_REGISTER_STRING_UNINITIALIZED_RESIZE(default_json_string,
json::__default_json_string);
}

#endif // WJR_JSON_DOCUMENT_HPP__
43 changes: 0 additions & 43 deletions include/wjr/memory/aligned_storage.hpp

This file was deleted.

4 changes: 2 additions & 2 deletions include/wjr/memory/inline_arg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
*/

#include <wjr/memory/aligned_storage.hpp>
#include <wjr/memory/uninitialized.hpp>

namespace wjr {

Expand All @@ -33,7 +33,7 @@ class inline_arg {
static constexpr bool is_inlined = true;

private:
using storage_type = aligned_storage<value_type>;
using storage_type = uninitialized<value_type>;

public:
inline_arg() = delete;
Expand Down
2 changes: 1 addition & 1 deletion include/wjr/memory/temporary_value_allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class temporary_value_allocator {

private:
Alloc &m_al;
aligned_storage<value_type> m_storage;
uninitialized<value_type> m_storage;
};

template <typename Alloc, typename... Args>
Expand Down
170 changes: 86 additions & 84 deletions include/wjr/memory/uninitialized.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
*
*/

#include <wjr/crtp/class_base.hpp>
#include <wjr/crtp/trivially_allocator_base.hpp>
#include <wjr/memory/aligned_storage.hpp>
#include <wjr/memory/detail.hpp>

namespace wjr {
Expand Down Expand Up @@ -671,116 +671,124 @@ OutputIt uninitialized_relocate_n_restrict_using_allocator(InputIt first, Size n
}
}

#if WJR_DEBUG_LEVEL > 1
#define WJR_HAS_DEBUG_UNINITIALIZED_CHECKER WJR_HAS_DEF
#endif
template <typename T, bool Constructor, bool Destructor>
struct __uninitialized_base;

template <typename T>
struct __aligned_storage_t {
alignas(T) char buf[sizeof(T)];
};

#define WJR_REGISTER_UNION_BASE(CON, DES) \
template <typename T> \
struct __uninitialized_base<T, CON, DES> { \
__uninitialized_base(const __uninitialized_base &) = default; \
__uninitialized_base(__uninitialized_base &&) = default; \
__uninitialized_base &operator=(const __uninitialized_base &) = default; \
__uninitialized_base &operator=(__uninitialized_base &&) = default; \
\
constexpr __uninitialized_base() WJR_PP_BOOL_IF(CON, = default, noexcept {}); \
\
template <typename... Args> \
constexpr __uninitialized_base(Args &&...args) noexcept( \
std::is_nothrow_constructible_v<T, Args...>) \
: m_value(std::forward<Args>(args)...) {} \
\
~__uninitialized_base() WJR_PP_BOOL_IF(DES, = default, noexcept {}); \
\
union { \
T m_value; \
__aligned_storage_t<T> m_storage; \
}; \
}

WJR_REGISTER_UNION_BASE(0, 0);
WJR_REGISTER_UNION_BASE(0, 1);
WJR_REGISTER_UNION_BASE(1, 0);
WJR_REGISTER_UNION_BASE(1, 1);

#undef WJR_REGISTER_UNION_BASE

template <typename T>
using __uninitialized_base_selector =
__uninitialized_base<T, std::is_trivially_default_constructible_v<T>,
std::is_trivially_destructible_v<T>>;

template <typename T>
struct __uninitialized_control_base : __uninitialized_base_selector<T> {
using Mybase = __uninitialized_base_selector<T>;
using Mybase::Mybase;

WJR_CONSTEXPR20 std::enable_if_t<std::is_copy_constructible_v<T>>
__copy_construct(const __uninitialized_control_base &other) noexcept(
std::is_nothrow_copy_constructible_v<T>) {
wjr::construct_at(std::addressof(this->m_value), other.m_value);
}

WJR_CONSTEXPR20 std::enable_if_t<std::is_move_constructible_v<T>>
__move_construct(__uninitialized_control_base &&other) noexcept(
std::is_nothrow_move_constructible_v<T>) {
wjr::construct_at(std::addressof(this->m_value), std::move(other.m_value));
}
};

template <typename T>
using __uninitialized_control_selector = control_special_members_base<
__uninitialized_control_base<T>,
std::is_trivially_copy_constructible_v<T> || !std::is_copy_constructible_v<T>,
std::is_trivially_move_constructible_v<T> || !std::is_move_constructible_v<T>, true,
true>;

template <typename T>
using __uninitialized_enabler =
enable_special_members_base<true, true, std::is_copy_constructible_v<T>,
std::is_move_constructible_v<T>, false, false>;

/**
* @class uninitialized
*
* @details Uninitialized object. Make trivially constructible and destructible of
* any type.+
*
* @details Trivially constructible and destructible uninitialized object. Copy/move
* constructor and assignment operators are deleted if the type is not trivially
* copy/move constructible/assignable.
* any type.
*
*/
template <typename T>
class uninitialized : aligned_storage<T> {
using Mybase = aligned_storage<T>;
class WJR_EMPTY_BASES uninitialized : __uninitialized_control_selector<T>,
__uninitialized_enabler<T> {
using Mybase = __uninitialized_control_selector<T>;

public:
using Mybase::Mybase;

WJR_ENABLE_DEFAULT_SPECIAL_MEMBERS(uninitialized);

template <typename... Args, WJR_REQUIRES(std::is_constructible_v<Mybase, Args...>)>
constexpr uninitialized(Args &&...args) noexcept(
std::is_nothrow_constructible_v<Mybase, Args...>)
: Mybase(std::forward<Args>(args)...) {
checker_set(true);
}
: Mybase(std::forward<Args>(args)...) {}

constexpr uninitialized(dctor_t) noexcept : Mybase() {}

template <typename... Args, WJR_REQUIRES(std::is_constructible_v<T, Args...>)>
constexpr T &
emplace(Args &&...args) noexcept(std::is_nothrow_constructible_v<Mybase, Args...>) {
if constexpr (!std::is_trivially_destructible_v<T>) {
check(false);
}

wjr::construct_at(get_unsafe(), std::forward<Args>(args)...);
checker_set(true);
return get();
wjr::construct_at(get(), std::forward<Args>(args)...);
return this->m_value;
}

constexpr void reset() noexcept(std::is_nothrow_destructible_v<T>) {
if constexpr (!std::is_trivially_destructible_v<T>) {
check(true);
}

std::destroy_at(get_unsafe());
checker_set(false);
std::destroy_at(get());
}

constexpr T &operator*() & noexcept {
check(true);
return Mybase::operator*();
}
constexpr const T &operator*() const & noexcept {
check(true);
return Mybase::operator*();
}
constexpr T &operator*() & noexcept { return this->m_value; }
constexpr const T &operator*() const & noexcept { return this->m_value; }
constexpr T &&operator*() && noexcept { return static_cast<T &&>(this->operator*()); }
constexpr const T &&operator*() const && noexcept {
return static_cast<const T &&>(this->operator*());
}

constexpr T *get_unsafe() noexcept { return Mybase::get(); }
constexpr const T *get_unsafe() const noexcept { return Mybase::get(); }

constexpr T *get() noexcept {
check(true);
return get_unsafe();
}

constexpr const T *get() const noexcept {
check(true);
return get_unsafe();
}
constexpr T *get() noexcept { return std::addressof(this->m_value); }
constexpr const T *get() const noexcept { return std::addressof(this->m_value); }

constexpr T *operator->() noexcept { return get(); }
constexpr const T *operator->() const noexcept { return get(); }

private:
#if WJR_HAS_DEBUG(UNINITIALIZED_CHECKER)
struct __checker {
constexpr void set(bool value) noexcept { m_initialized = value; }
constexpr void check(bool value) const noexcept {
WJR_ASSERT_L0(m_initialized == value, "Expected ",
(value ? "initialized" : "uninitialized"),
" value when using an uninitialized object.");
}

~__checker() noexcept {
if constexpr (!std::is_trivially_destructible_v<T>) {
check(false);
}
}

bool m_initialized = false;
};

__checker m_checker;

constexpr void checker_set(bool value) noexcept { m_checker.set(value); }
constexpr void check(bool value) const noexcept { m_checker.check(value); }
#else
constexpr static void checker_set(bool) noexcept {}
constexpr static void check(bool) noexcept {}
#endif
};

/// @private
Expand All @@ -805,13 +813,7 @@ class __lazy_initialized_base<T, false> : public uninitialized<T> {

/// @private
template <typename T>
using lazy_initialized_base = __lazy_initialized_base<T,
#if WJR_HAS_DEBUG(UNINITIALIZED_CHECKER)
false
#else
std::is_trivially_destructible_v<T>
#endif
>;
using lazy_initialized_base = __lazy_initialized_base<T, false>;

template <typename T>
class lazy_initialized : public lazy_initialized_base<T> {
Expand Down
Loading

0 comments on commit c5b426e

Please sign in to comment.