Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit ca75535

Browse files
committed
Add core.stdcpp.allocator
1 parent cadb7cc commit ca75535

File tree

6 files changed

+136
-0
lines changed

6 files changed

+136
-0
lines changed

changelog/std_allocator.dd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Added `core.stdcpp.allocator`
2+
3+
Added `core.stdcpp.allocator`, which exposes the C++ `std::allocator<T>` class.
4+
This is a required foundation for any of the allocating STL container types.

mak/COPY

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ COPY=\
5050
$(IMPDIR)\core\stdc\wchar_.d \
5151
$(IMPDIR)\core\stdc\wctype.d \
5252
\
53+
$(IMPDIR)\core\stdcpp\allocator.d \
5354
$(IMPDIR)\core\stdcpp\array.d \
5455
$(IMPDIR)\core\stdcpp\exception.d \
5556
$(IMPDIR)\core\stdcpp\new_.d \

mak/DOCS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ DOCS=\
3939
$(DOCDIR)\core_stdc_wchar_.html \
4040
$(DOCDIR)\core_stdc_wctype.html \
4141
\
42+
$(DOCDIR)\core_stdcpp_allocator.html \
4243
$(DOCDIR)\core_stdcpp_array.html \
4344
$(DOCDIR)\core_stdcpp_exception.html \
4445
$(DOCDIR)\core_stdcpp_new_.html \

mak/SRCS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ SRCS=\
5050
src\core\stdc\wchar_.d \
5151
src\core\stdc\wctype.d \
5252
\
53+
src\core\stdcpp\allocator.d \
5354
src\core\stdcpp\array.d \
5455
src\core\stdcpp\new_.d \
5556
src\core\stdcpp\string_view.d \

mak/WINDOWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ $(IMPDIR)\core\stdc\wchar_.d : src\core\stdc\wchar_.d
189189
$(IMPDIR)\core\stdc\wctype.d : src\core\stdc\wctype.d
190190
copy $** $@
191191

192+
$(IMPDIR)\core\stdcpp\allocator.d : src\core\stdcpp\allocator.d
193+
copy $** $@
194+
192195
$(IMPDIR)\core\stdcpp\array.d : src\core\stdcpp\array.d
193196
copy $** $@
194197

src/core/stdcpp/allocator.d

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/**
2+
* D binding to C++ std::allocator.
3+
*
4+
* Copyright: Copyright (c) 2019 D Language Foundation
5+
* License: Distributed under the
6+
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7+
* (See accompanying file LICENSE)
8+
* Authors: Manu Evans
9+
* Source: $(DRUNTIMESRC core/stdcpp/allocator.d)
10+
*/
11+
12+
module core.stdcpp.allocator;
13+
14+
import core.stdcpp.new_;
15+
import core.stdcpp.xutility : __cpp_sized_deallocation, __cpp_aligned_new;
16+
17+
// some versions of VS require a `* const` pointer mangling hack
18+
// we need a way to supply the target VS version to the compile
19+
version (CppRuntime_Microsoft)
20+
version = NeedsMangleHack;
21+
22+
/**
23+
* Allocators are classes that define memory models to be used by some parts of
24+
* the C++ Standard Library, and most specifically, by STL containers.
25+
*/
26+
extern(C++, class)
27+
extern(C++, "std")
28+
struct allocator(T)
29+
{
30+
static assert(!is(T == const), "The C++ Standard forbids containers of const elements because allocator!(const T) is ill-formed.");
31+
static assert(!is(T == immutable), "immutable is not representable in C++");
32+
static assert(!is(T == class), "Instantiation with `class` is not supported; D can't mangle the base (non-pointer) type of a class. Use `extern (C++, class) struct T { ... }` instead.");
33+
34+
///
35+
alias value_type = T;
36+
37+
version (CppRuntime_Microsoft)
38+
{
39+
///
40+
T* allocate(size_t count) @nogc;
41+
///
42+
void deallocate(T* ptr, size_t count) @nogc;
43+
44+
///
45+
enum size_t max_size = size_t.max / T.sizeof;
46+
47+
version (NeedsMangleHack)
48+
{
49+
// HACK: workaround to make `deallocate` link as a `T * const`
50+
private extern (D) enum string constHack(string name) = (){
51+
version (Win64)
52+
enum sub = "AAXPE";
53+
else
54+
enum sub = "AEXPA";
55+
foreach (i; 0 .. name.length - sub.length)
56+
if (name[i .. i + sub.length] == sub[])
57+
return name[0 .. i + 3] ~ 'Q' ~ name[i + 4 .. $];
58+
assert(false, "substitution string not found!");
59+
}();
60+
pragma(linkerDirective, "/alternatename:" ~ deallocate.mangleof ~ "=" ~ constHack!(deallocate.mangleof));
61+
}
62+
}
63+
else version (CppRuntime_Gcc)
64+
{
65+
///
66+
T* allocate(size_t count, const(void)* = null) @nogc
67+
{
68+
// if (count > max_size)
69+
// std::__throw_bad_alloc();
70+
71+
static if (__cpp_aligned_new && T.alignof > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
72+
return cast(T*)__cpp_new_aligned(count * T.sizeof, cast(align_val_t)T.alignof);
73+
else
74+
return cast(T*)__cpp_new(count * T.sizeof);
75+
}
76+
///
77+
void deallocate(T* ptr, size_t count) @nogc
78+
{
79+
// NOTE: GCC doesn't seem to use the sized delete when it's available...
80+
81+
static if (__cpp_aligned_new && T.alignof > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
82+
__cpp_delete_aligned(cast(void*)ptr, cast(align_val_t)T.alignof);
83+
else
84+
__cpp_delete(cast(void*)ptr);
85+
}
86+
87+
///
88+
enum size_t max_size = (ptrdiff_t.max < size_t.max ? cast(size_t)ptrdiff_t.max : size_t.max) / T.sizeof;
89+
}
90+
else version (CppRuntime_Clang)
91+
{
92+
///
93+
T* allocate(size_t count, const(void)* = null) @nogc
94+
{
95+
// if (count > max_size)
96+
// __throw_length_error("allocator!T.allocate(size_t n) 'n' exceeds maximum supported size");
97+
98+
static if (__cpp_aligned_new && T.alignof > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
99+
return cast(T*)__cpp_new_aligned(count * T.sizeof, cast(align_val_t)T.alignof);
100+
else
101+
return cast(T*)__cpp_new(count * T.sizeof);
102+
}
103+
///
104+
void deallocate(T* ptr, size_t count) @nogc
105+
{
106+
static if (__cpp_aligned_new && T.alignof > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
107+
{
108+
static if (__cpp_sized_deallocation)
109+
return __cpp_delete_size_aligned(cast(void*)ptr, count * T.sizeof, cast(align_val_t)T.alignof);
110+
else
111+
return __cpp_delete_aligned(cast(void*)ptr, cast(align_val_t)T.alignof);
112+
}
113+
else static if (__cpp_sized_deallocation)
114+
return __cpp_delete_size(cast(void*)ptr, count * T.sizeof);
115+
else
116+
return __cpp_delete(cast(void*)ptr);
117+
}
118+
119+
///
120+
enum size_t max_size = size_t.max / T.sizeof;
121+
}
122+
else
123+
{
124+
static assert(false, "C++ runtime not supported");
125+
}
126+
}

0 commit comments

Comments
 (0)