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
12module core.stdcpp.memory;
13
14public import core.stdcpp.allocator;
15
16import core.stdcpp.xutility : StdNamespace;
17
18extern(C++, (StdNamespace)):
19
20///
21unique_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///
30struct 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///
45extern(C++, class)
46struct unique_ptr(T, Deleter = default_delete!T)
47{
48extern(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
74nothrow 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
155private:
156
157template ClassOrPtr(T)
158{
159    static if (is(T == class))
160        alias ClassOrPtr = T;
161    else
162        alias ClassOrPtr = T*;
163}
164