Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions stl/inc/xpolymorphic_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include <utility>
#include <xmemory>

#if _HAS_CXX20
#include <memory>
#endif // _HAS_CXX20

#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
Expand Down Expand Up @@ -186,7 +190,11 @@ namespace pmr {
}

// CLASS TEMPLATE polymorphic_allocator
#if _HAS_CXX20 && defined(__cpp_lib_byte)
template <class _Ty = byte>
#else
template <class _Ty>
#endif // _HAS_CXX20 && defined(__cpp_lib_byte)
class polymorphic_allocator {
public:
template <class>
Expand Down Expand Up @@ -229,6 +237,49 @@ namespace pmr {
_Uses_allocator_construct(_Ptr, _Al, *this, _STD forward<_Types>(_Args)...);
}

#if _HAS_CXX20

_NODISCARD __declspec(allocator) void* allocate_bytes(
const size_t _Bytes, const size_t _Align = alignof(max_align_t)) {
return _Resource->allocate(_Bytes, _Align);
}

void deallocate_bytes(void* const _Ptr, const size_t _Bytes,
const size_t _Align = alignof(max_align_t)) noexcept /* strengthened */ {
_Resource->deallocate(_Ptr, _Bytes, _Align);
}

template <class _Uty>
_NODISCARD __declspec(allocator) _Uty* allocate_object(_CRT_GUARDOVERFLOW const size_t _Count = 1) {
void* const _Vp = this->allocate_bytes(_Get_size_of_n<sizeof(_Uty)>(_Count), alignof(_Uty));
return static_cast<_Uty*>(_Vp);
}

template <class _Uty>
void deallocate_object(_Uty* const _Ptr, const size_t _Count = 1) noexcept /* strengthened */ {
this->deallocate_bytes(_Ptr, _Count * sizeof(_Uty), alignof(_Uty));
}

template <class _Uty, class... _Types>
_NODISCARD __declspec(allocator) _Uty* new_object(_Types&&... _Args) {
_Uty* _Ptr = this->allocate_object<_Uty>();
_TRY_BEGIN
this->construct(_Ptr, _STD forward<_Types>(_Args)...);
_CATCH_ALL
this->deallocate_object(_Ptr);
_RERAISE;
_CATCH_END
return _Ptr;
}

template <class _Uty>
void delete_object(_Uty* const _Ptr) noexcept /* strengthened */ {
_STD destroy_at(_Ptr);
this->deallocate_object(_Ptr);
}

#endif // _HAS_CXX20

_NODISCARD polymorphic_allocator select_on_container_copy_construction() const noexcept /* strengthened */ {
// don't propagate on copy
return {};
Expand Down
2 changes: 2 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
// P0202R3 constexpr For <algorithm> And exchange()
// P0318R1 unwrap_reference, unwrap_ref_decay
// P0325R4 to_array()
// P0339R6 polymorphic_allocator<>
// P0356R5 bind_front()
// P0357R3 Supporting Incomplete Types In reference_wrapper
// P0415R1 constexpr For <complex> (Again)
Expand Down Expand Up @@ -1192,6 +1193,7 @@
#define __cpp_lib_latch 201907L
#define __cpp_lib_list_remove_return_type 201806L
#define __cpp_lib_math_constants 201907L
#define __cpp_lib_polymorphic_allocator 201902L
#define __cpp_lib_remove_cvref 201711L
#define __cpp_lib_semaphore 201907L
#define __cpp_lib_shift 201806L
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ tests\P0220R1_sample
tests\P0220R1_searchers
tests\P0220R1_string_view
tests\P0325R4_to_array
tests\P0339R6_polymorphic_allocator
tests\P0356R5_bind_front
tests\P0357R3_supporting_incomplete_types_in_reference_wrapper
tests\P0414R2_shared_ptr_for_arrays
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0339R6_polymorphic_allocator/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
108 changes: 108 additions & 0 deletions tests/std/tests/P0339R6_polymorphic_allocator/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <cassert>
#include <cstddef>
#include <memory>
#include <memory_resource>
#include <numeric>

using std::pmr::polymorphic_allocator;

void allocate_bytes_test() {
constexpr int N = 5;

polymorphic_allocator<> alloc{};

void* vp = alloc.allocate_bytes(sizeof(int) * N, alignof(int));

int* arr = static_cast<int*>(vp);

for (int i = 0; i < N; ++i) {
alloc.construct(arr + i, i);
}

for (int i = 0; i < N; ++i) {
assert(arr[i] == i);
}

for (int i = 0; i < N; ++i) {
std::destroy_at(arr + i);
}

alloc.deallocate_bytes(vp, sizeof(int) * N, alignof(int));

void* vp2 = alloc.allocate_bytes(sizeof(int));
assert(reinterpret_cast<std::intptr_t>(vp2) % alignof(std::max_align_t) == 0);
alloc.deallocate_bytes(vp2, sizeof(int));
}

void allocate_object_test() {
constexpr int N = 10;

polymorphic_allocator<> alloc{};

int* arr = alloc.allocate_object<int>(N);

for (int i = 0; i < N; ++i) {
alloc.construct(arr + i, i);
}

for (int i = 0; i < N; ++i) {
assert(arr[i] == i);
}

for (int i = 0; i < N; ++i) {
std::destroy_at(arr + i);
}

alloc.deallocate_object(arr, N);

// N = 1
int* p = alloc.allocate_object<int>();
alloc.construct(p, 20);
assert(*p == 20);
std::destroy_at(p);
alloc.deallocate_object(p);
}

void allocate_object_overflow_test() {
constexpr auto threshold = std::numeric_limits<std::size_t>::max() / sizeof(int);

polymorphic_allocator<> alloc{};

try {
int* vp = alloc.allocate_object<int>(threshold);
alloc.deallocate_object(vp, threshold);
} catch (const std::bad_alloc&) {
} catch (...) {
assert(false);
}

try {
[[maybe_unused]] int* vp = alloc.allocate_object<int>(threshold + 1);
} catch (const std::bad_array_new_length&) {
return;
} catch (...) {
assert(false);
}
assert(false);
}

void new_object_test() {
polymorphic_allocator<> alloc{};

int* p = alloc.new_object<int>(20);

assert(*p == 20);

alloc.delete_object(p);
}


int main() {
allocate_bytes_test();
allocate_object_test();
allocate_object_overflow_test();
new_object_test();
}
14 changes: 14 additions & 0 deletions tests/std/tests/VSO_0157762_feature_test_macros/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1064,6 +1064,20 @@ STATIC_ASSERT(__cpp_lib_parallel_algorithm == 201603L);
#endif
#endif

#if _HAS_CXX20
#ifndef __cpp_lib_polymorphic_allocator
#error __cpp_lib_polymorphic_allocator is not defined
#elif __cpp_lib_polymorphic_allocator != 201902L
#error __cpp_lib_polymorphic_allocator is not 201902L
#else
STATIC_ASSERT(__cpp_lib_polymorphic_allocator == 201902L);
#endif
#else
#ifdef __cpp_lib_polymorphic_allocator
#error __cpp_lib_polymorphic_allocator is defined
#endif
#endif

#ifndef __cpp_lib_quoted_string_io
#error __cpp_lib_quoted_string_io is not defined
#elif __cpp_lib_quoted_string_io != 201304L
Expand Down