1 /**
2 * D binding to C++ <memory>.
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/memory.d)
10 */
11 
12 module core.stdcpp.memory;
13 
14 public import core.stdcpp.allocator;
15 
16 import core.stdcpp.xutility : StdNamespace;
17 
18 extern(C++, (StdNamespace)):
19 
20 ///
21 unique_ptr!T make_unique(T, Args...)(auto ref Args args)
22 {
23     import core.lifetime : forward;
24     import core.stdcpp.new_ : cpp_new;
25 
26     return unique_ptr!T(cpp_new!T(forward!args));
27 }
28 
29 ///
30 struct default_delete(T)
31 {
32     ///
33     alias pointer = ClassOrPtr!T;
34 
35     ///
36     void opCall()(pointer ptr) const
37     {
38         import core.stdcpp.new_ : cpp_delete;
39 
40         cpp_delete(ptr);
41     }
42 }
43 
44 ///
45 extern(C++, class)
46 struct unique_ptr(T, Deleter = default_delete!T)
47 {
48 extern(D):
49     ///
50     this(this) @disable;
51 
52     ///
53     ~this()
54     {
55         reset();
56     }
57 
58     ///
59     ref unique_ptr opAssign(typeof(null))
60     {
61         reset();
62         return this;
63     }
64 
65     ///
66     void reset(pointer p = null)
67     {
68         pointer t = __ptr();
69         __ptr() = p;
70         if (t)
71             get_deleter()(t);
72     }
73 
74 nothrow pure @safe @nogc:
75     ///
76     alias pointer = ClassOrPtr!T;
77     ///
78     alias element_type = T;
79     ///
80     alias deleter_type = Deleter;
81 
82     ///
83     this(pointer ptr)
84     {
85         __ptr() = ptr;
86     }
87 
88     ///
89     inout(pointer) get() inout nothrow
90     {
91         return __ptr();
92     }
93 
94     ///
95     bool opCast(T : bool)() const nothrow
96     {
97         return __ptr() != null;
98     }
99 
100     ///
101     pointer release() nothrow
102     {
103         pointer t = __ptr();
104         __ptr() = null;
105         return t;
106     }
107 
108 //    void swap(ref unique_ptr u) nothrow
109 //    {
110 //        __ptr_.swap(__u.__ptr_);
111 //    }
112 
113     version (CppRuntime_Microsoft)
114     {
115         ///
116         ref inout(deleter_type) get_deleter() inout nothrow { return _Mypair._Myval1; }
117 
118     private:
119         import core.stdcpp.xutility : _Compressed_pair;
120 
121         ref pointer __ptr() nothrow { return _Mypair._Myval2; }
122         inout(pointer) __ptr() inout nothrow { return _Mypair._Myval2; }
123 
124         _Compressed_pair!(Deleter, pointer) _Mypair;
125     }
126     else version (CppRuntime_Gcc)
127     {
128         ///
129         ref inout(deleter_type) get_deleter() inout nothrow { return _M_t.get!1; }
130 
131     private:
132         import core.stdcpp.tuple : tuple, get;
133 
134         ref pointer __ptr() nothrow { return _M_t.get!0; }
135         inout(pointer) __ptr() inout nothrow { return _M_t.get!0; }
136 
137         tuple!(pointer, Deleter) _M_t;
138     }
139     else version (CppRuntime_Clang)
140     {
141         ///
142         ref inout(deleter_type) get_deleter() inout nothrow { return __ptr_.second; }
143 
144     private:
145         import core.stdcpp.xutility : __compressed_pair;
146 
147         ref pointer __ptr() nothrow { return __ptr_.first; }
148         inout(pointer) __ptr() inout nothrow { return __ptr_.first; }
149 
150         __compressed_pair!(pointer, deleter_type) __ptr_;
151     }
152 }
153 
154 
155 private:
156 
157 template ClassOrPtr(T)
158 {
159     static if (is(T == class))
160         alias ClassOrPtr = T;
161     else
162         alias ClassOrPtr = T*;
163 }