Skip to content

Commit 2d38a6a

Browse files
committed
Reimplement the allocator required for the container type with $new
1 parent 831225f commit 2d38a6a

8 files changed

+115
-103
lines changed

include/libipc/mem/polymorphic_allocator.h renamed to include/libipc/mem/bytes_allocator.h

+3-86
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* \file libipc/polymorphic_allocator
2+
* \file libipc/bytes_allocator.h
33
* \author mutouyun ([email protected])
44
* \brief A generic polymorphic memory allocator.
55
*/
@@ -50,13 +50,13 @@ using is_memory_resource =
5050
* \brief An allocator which exhibits different allocation behavior
5151
* depending upon the memory resource from which it is constructed.
5252
*
53-
* \note Unlike `std::pmr::polymorphic_allocator`, it does not
53+
* \note Unlike `std::pmr::container_allocator`, it does not
5454
* rely on a specific inheritance relationship and only restricts
5555
* the interface behavior of the incoming memory resource object to
5656
* conform to `std::pmr::memory_resource`.
5757
*
5858
* \see https://en.cppreference.com/w/cpp/memory/memory_resource
59-
* https://en.cppreference.com/w/cpp/memory/polymorphic_allocator
59+
* https://en.cppreference.com/w/cpp/memory/container_allocator
6060
*/
6161
class LIBIPC_EXPORT bytes_allocator {
6262

@@ -159,88 +159,5 @@ class LIBIPC_EXPORT bytes_allocator {
159159
}
160160
};
161161

162-
/**
163-
* \brief An allocator that can be used by all standard library containers,
164-
* based on ipc::bytes_allocator.
165-
*
166-
* \see https://en.cppreference.com/w/cpp/memory/allocator
167-
* https://en.cppreference.com/w/cpp/memory/polymorphic_allocator
168-
*/
169-
template <typename T>
170-
class polymorphic_allocator {
171-
172-
template <typename U>
173-
friend class polymorphic_allocator;
174-
175-
public:
176-
// type definitions
177-
typedef T value_type;
178-
typedef value_type * pointer;
179-
typedef const value_type *const_pointer;
180-
typedef value_type & reference;
181-
typedef const value_type &const_reference;
182-
typedef std::size_t size_type;
183-
typedef std::ptrdiff_t difference_type;
184-
185-
private:
186-
bytes_allocator alloc_;
187-
188-
public:
189-
// the other type of std_allocator
190-
template <typename U>
191-
struct rebind {
192-
using other = polymorphic_allocator<U>;
193-
};
194-
195-
polymorphic_allocator() noexcept {}
196-
197-
template <typename P, is_memory_resource<P> = true>
198-
polymorphic_allocator(P *p_mr) noexcept : alloc_(p_mr) {}
199-
200-
// construct by copying (do nothing)
201-
polymorphic_allocator (polymorphic_allocator<T> const &) noexcept {}
202-
polymorphic_allocator& operator=(polymorphic_allocator<T> const &) noexcept { return *this; }
203-
204-
// construct from a related allocator (do nothing)
205-
template <typename U> polymorphic_allocator (polymorphic_allocator<U> const &) noexcept {}
206-
template <typename U> polymorphic_allocator &operator=(polymorphic_allocator<U> const &) noexcept { return *this; }
207-
208-
polymorphic_allocator (polymorphic_allocator &&) noexcept = default;
209-
polymorphic_allocator& operator=(polymorphic_allocator &&) noexcept = default;
210-
211-
constexpr size_type max_size(void) const noexcept {
212-
return (std::numeric_limits<size_type>::max)() / sizeof(value_type);
213-
}
214-
215-
pointer allocate(size_type count) noexcept {
216-
if (count == 0) return nullptr;
217-
if (count > this->max_size()) return nullptr;
218-
return static_cast<pointer>(alloc_.allocate(count * sizeof(value_type), alignof(T)));
219-
}
220-
221-
void deallocate(pointer p, size_type count) noexcept {
222-
alloc_.deallocate(p, count * sizeof(value_type), alignof(T));
223-
}
224-
225-
template <typename... P>
226-
static void construct(pointer p, P && ... params) {
227-
std::ignore = ipc::construct<T>(p, std::forward<P>(params)...);
228-
}
229-
230-
static void destroy(pointer p) {
231-
std::ignore = ipc::destroy(p);
232-
}
233-
};
234-
235-
template <typename T, typename U>
236-
constexpr bool operator==(polymorphic_allocator<T> const &, polymorphic_allocator<U> const &) noexcept {
237-
return true;
238-
}
239-
240-
template <typename T, typename U>
241-
constexpr bool operator!=(polymorphic_allocator<T> const &, polymorphic_allocator<U> const &) noexcept {
242-
return false;
243-
}
244-
245162
} // namespace mem
246163
} // namespace ipc

include/libipc/mem/central_cache_allocator.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#pragma once
77

88
#include "libipc/imp/export.h"
9-
#include "libipc/mem/polymorphic_allocator.h"
9+
#include "libipc/mem/bytes_allocator.h"
1010

1111
namespace ipc {
1212
namespace mem {
+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* \file libipc/container_allocator.h
3+
* \author mutouyun ([email protected])
4+
* \brief An allocator that can be used by all standard library containers.
5+
*/
6+
#pragma once
7+
8+
#include <cstddef>
9+
#include <utility>
10+
11+
#include "libipc/imp/uninitialized.h"
12+
#include "libipc/mem/new.h"
13+
14+
namespace ipc {
15+
namespace mem {
16+
17+
/**
18+
* \brief An allocator that can be used by all standard library containers.
19+
*
20+
* \see https://en.cppreference.com/w/cpp/memory/allocator
21+
* https://en.cppreference.com/w/cpp/memory/polymorphic_allocator
22+
*/
23+
template <typename T>
24+
class container_allocator {
25+
26+
template <typename U>
27+
friend class container_allocator;
28+
29+
public:
30+
// type definitions
31+
typedef T value_type;
32+
typedef value_type * pointer;
33+
typedef const value_type *const_pointer;
34+
typedef value_type & reference;
35+
typedef const value_type &const_reference;
36+
typedef std::size_t size_type;
37+
typedef std::ptrdiff_t difference_type;
38+
39+
// the other type of std_allocator
40+
template <typename U>
41+
struct rebind {
42+
using other = container_allocator<U>;
43+
};
44+
45+
container_allocator() noexcept {}
46+
47+
// construct by copying (do nothing)
48+
container_allocator (container_allocator<T> const &) noexcept {}
49+
container_allocator& operator=(container_allocator<T> const &) noexcept { return *this; }
50+
51+
// construct from a related allocator (do nothing)
52+
template <typename U> container_allocator (container_allocator<U> const &) noexcept {}
53+
template <typename U> container_allocator &operator=(container_allocator<U> const &) noexcept { return *this; }
54+
55+
container_allocator (container_allocator &&) noexcept = default;
56+
container_allocator& operator=(container_allocator &&) noexcept = default;
57+
58+
constexpr size_type max_size() const noexcept {
59+
return 1;
60+
}
61+
62+
pointer allocate(size_type count) noexcept {
63+
if (count == 0) return nullptr;
64+
if (count > this->max_size()) return nullptr;
65+
return mem::$new<value_type>();
66+
}
67+
68+
void deallocate(pointer p, size_type count) noexcept {
69+
if (count == 0) return;
70+
if (count > this->max_size()) return;
71+
mem::$delete(p);
72+
}
73+
74+
template <typename... P>
75+
static void construct(pointer p, P && ... params) {
76+
std::ignore = ipc::construct<T>(p, std::forward<P>(params)...);
77+
}
78+
79+
static void destroy(pointer p) {
80+
std::ignore = ipc::destroy(p);
81+
}
82+
};
83+
84+
template <typename T, typename U>
85+
constexpr bool operator==(container_allocator<T> const &, container_allocator<U> const &) noexcept {
86+
return true;
87+
}
88+
89+
template <typename T, typename U>
90+
constexpr bool operator!=(container_allocator<T> const &, container_allocator<U> const &) noexcept {
91+
return false;
92+
}
93+
94+
} // namespace mem
95+
} // namespace ipc

include/libipc/mem/memory_resource.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include "libipc/imp/export.h"
1212
#include "libipc/imp/span.h"
1313
#include "libipc/imp/byte.h"
14-
#include "libipc/mem/polymorphic_allocator.h"
14+
#include "libipc/mem/bytes_allocator.h"
1515

1616
namespace ipc {
1717
namespace mem {

src/libipc/mem/polymorphic_allocator.cpp renamed to src/libipc/mem/bytes_allocator.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include <algorithm> // std::swap
33

44
#include "libipc/imp/log.h"
5-
#include "libipc/mem/polymorphic_allocator.h"
5+
#include "libipc/mem/bytes_allocator.h"
66
#include "libipc/mem/memory_resource.h"
77

88
namespace ipc {

src/libipc/mem/central_cache_allocator.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include "libipc/def.h"
77
#include "libipc/imp/detect_plat.h"
88
#include "libipc/imp/byte.h"
9-
#include "libipc/mem/polymorphic_allocator.h"
9+
#include "libipc/mem/bytes_allocator.h"
1010
#include "libipc/mem/memory_resource.h"
1111

1212
namespace ipc {

src/libipc/mem/resource.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#include "libipc/def.h"
88
#include "libipc/imp/fmt.h"
9-
#include "libipc/mem/polymorphic_allocator.h"
9+
#include "libipc/mem/container_allocator.h"
1010

1111
namespace ipc {
1212

@@ -15,12 +15,12 @@ struct hash : public std::hash<T> {};
1515

1616
template <typename Key, typename T>
1717
using unordered_map = std::unordered_map<
18-
Key, T, ipc::hash<Key>, std::equal_to<Key>, ipc::mem::polymorphic_allocator<std::pair<Key const, T>>
18+
Key, T, ipc::hash<Key>, std::equal_to<Key>, ipc::mem::container_allocator<std::pair<Key const, T>>
1919
>;
2020

2121
template <typename Key, typename T>
2222
using map = std::map<
23-
Key, T, std::less<Key>, ipc::mem::polymorphic_allocator<std::pair<Key const, T>>
23+
Key, T, std::less<Key>, ipc::mem::container_allocator<std::pair<Key const, T>>
2424
>;
2525

2626
/// \brief Check string validity.

test/mem/test_mem_allocator.cpp renamed to test/mem/test_mem_bytes_allocator.cpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
# include <memory_resource>
99
#endif
1010

11-
#include "libipc/mem/polymorphic_allocator.h"
11+
#include "libipc/mem/bytes_allocator.h"
1212
#include "libipc/mem/memory_resource.h"
1313

14-
TEST(polymorphic_allocator, ctor) {
14+
TEST(bytes_allocator, ctor) {
1515
ipc::mem::bytes_allocator alc;
1616
SUCCEED();
1717
}
1818

19-
TEST(polymorphic_allocator, ctor_value_initialization) {
19+
TEST(bytes_allocator, ctor_value_initialization) {
2020
ipc::mem::bytes_allocator alc{};
2121
auto p = alc.allocate(128);
2222
EXPECT_NE(p, nullptr);
@@ -37,14 +37,14 @@ class dummy_resource {
3737

3838
} // namespace
3939

40-
TEST(polymorphic_allocator, memory_resource_traits) {
40+
TEST(bytes_allocator, memory_resource_traits) {
4141
EXPECT_FALSE(ipc::mem::has_allocate<void>::value);
4242
EXPECT_FALSE(ipc::mem::has_allocate<int>::value);
4343
EXPECT_FALSE(ipc::mem::has_allocate<std::vector<int>>::value);
4444
EXPECT_FALSE(ipc::mem::has_allocate<std::allocator<int>>::value);
4545
#if defined(LIBIMP_CPP_17) && defined(__cpp_lib_memory_resource)
4646
EXPECT_TRUE (ipc::mem::has_allocate<std::ipc::mem::memory_resource>::value);
47-
EXPECT_TRUE (ipc::mem::has_allocate<std::ipc::mem::polymorphic_allocator<int>>::value);
47+
EXPECT_TRUE (ipc::mem::has_allocate<std::ipc::mem::container_allocator<int>>::value);
4848
#endif
4949

5050
EXPECT_FALSE(ipc::mem::has_deallocate<void>::value);
@@ -53,11 +53,11 @@ TEST(polymorphic_allocator, memory_resource_traits) {
5353
EXPECT_FALSE(ipc::mem::has_deallocate<std::allocator<int>>::value);
5454
#if defined(LIBIMP_CPP_17) && defined(__cpp_lib_memory_resource)
5555
EXPECT_TRUE (ipc::mem::has_deallocate<std::ipc::mem::memory_resource>::value);
56-
EXPECT_FALSE(ipc::mem::has_deallocate<std::ipc::mem::polymorphic_allocator<int>>::value);
56+
EXPECT_FALSE(ipc::mem::has_deallocate<std::ipc::mem::container_allocator<int>>::value);
5757
#endif
5858
}
5959

60-
TEST(polymorphic_allocator, ctor_copy_move) {
60+
TEST(bytes_allocator, ctor_copy_move) {
6161
ipc::mem::new_delete_resource mem_res;
6262
dummy_resource dummy_res;
6363
ipc::mem::bytes_allocator alc1{&mem_res}, alc2{&dummy_res};
@@ -79,7 +79,7 @@ TEST(polymorphic_allocator, ctor_copy_move) {
7979
ASSERT_NO_THROW(alc5.deallocate(p, 128));
8080
}
8181

82-
TEST(polymorphic_allocator, swap) {
82+
TEST(bytes_allocator, swap) {
8383
ipc::mem::new_delete_resource mem_res;
8484
dummy_resource dummy_res;
8585
ipc::mem::bytes_allocator alc1{&mem_res}, alc2{&dummy_res};
@@ -90,14 +90,14 @@ TEST(polymorphic_allocator, swap) {
9090
ASSERT_EQ(alc1.allocate(128), nullptr);
9191
}
9292

93-
TEST(polymorphic_allocator, invalid_alloc_free) {
93+
TEST(bytes_allocator, invalid_alloc_free) {
9494
ipc::mem::bytes_allocator alc1;
9595
EXPECT_EQ(alc1.allocate(0), nullptr);
9696
EXPECT_NO_THROW(alc1.deallocate(nullptr, 128));
9797
EXPECT_NO_THROW(alc1.deallocate(nullptr, 0));
9898
EXPECT_NO_THROW(alc1.deallocate(&alc1, 0));
9999
}
100100

101-
TEST(polymorphic_allocator, sizeof) {
101+
TEST(bytes_allocator, sizeof) {
102102
EXPECT_EQ(sizeof(ipc::mem::bytes_allocator), sizeof(void *) * 2);
103103
}

0 commit comments

Comments
 (0)