Unreviewed, rolling out r234489.
[WebKit-https.git] / Source / WTF / wtf / CagedUniquePtr.h
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include <wtf/CagedPtr.h>
29
30 namespace WTF {
31
32 template<Gigacage::Kind kind, typename T, typename Enable = void>
33 class CagedUniquePtr : public CagedPtr<kind, T> {
34 public:
35     CagedUniquePtr(T* ptr = nullptr)
36         : CagedPtr<kind, T>(ptr)
37     {
38     }
39     
40     CagedUniquePtr(CagedUniquePtr&& ptr)
41         : CagedPtr<kind, T>(ptr.m_ptr)
42     {
43         ptr.m_ptr = nullptr;
44     }
45     
46     CagedUniquePtr(const CagedUniquePtr&) = delete;
47     
48     template<typename... Arguments>
49     static CagedUniquePtr create(Arguments&&... arguments)
50     {
51         T* result = static_cast<T*>(Gigacage::malloc(kind, sizeof(T)));
52         new (result) T(std::forward<Arguments>(arguments)...);
53         return CagedUniquePtr(result);
54     }
55     
56     CagedUniquePtr& operator=(CagedUniquePtr&& ptr)
57     {
58         destroy();
59         this->m_ptr = ptr.m_ptr;
60         ptr.m_ptr = nullptr;
61         return *this;
62     }
63     
64     CagedUniquePtr& operator=(const CagedUniquePtr&) = delete;
65     
66     ~CagedUniquePtr()
67     {
68         destroy();
69     }
70     
71 private:
72     void destroy()
73     {
74         if (!this->m_ptr)
75             return;
76         this->m_ptr->~T();
77         Gigacage::free(kind, this->m_ptr);
78     }
79 };
80
81 template<Gigacage::Kind kind, typename T>
82 class CagedUniquePtr<kind, T[], typename std::enable_if<std::is_trivially_destructible<T>::value>::type> : public CagedPtr<kind, T> {
83 public:
84     CagedUniquePtr() : CagedPtr<kind, T>() { }
85     
86     CagedUniquePtr(T* ptr)
87         : CagedPtr<kind, T>(ptr)
88     {
89     }
90     
91     CagedUniquePtr(CagedUniquePtr&& ptr)
92         : CagedPtr<kind, T>(ptr.m_ptr)
93     {
94         ptr.m_ptr = nullptr;
95     }
96     
97     CagedUniquePtr(const CagedUniquePtr&) = delete;
98     
99     template<typename... Arguments>
100     static CagedUniquePtr create(size_t count, Arguments&&... arguments)
101     {
102         T* result = static_cast<T*>(Gigacage::mallocArray(kind, count, sizeof(T)));
103         while (count--)
104             new (result + count) T(std::forward<Arguments>(arguments)...);
105         return CagedUniquePtr(result);
106     }
107     
108     CagedUniquePtr& operator=(CagedUniquePtr&& ptr)
109     {
110         destroy();
111         this->m_ptr = ptr.m_ptr;
112         ptr.m_ptr = nullptr;
113         return *this;
114     }
115     
116     CagedUniquePtr& operator=(const CagedUniquePtr&) = delete;
117     
118     ~CagedUniquePtr()
119     {
120         destroy();
121     }
122     
123 private:
124     void destroy()
125     {
126         if (!this->m_ptr)
127             return;
128         Gigacage::free(kind, this->m_ptr);
129     }
130 };
131
132 template<Gigacage::Kind kind, typename T>
133 class CagedUniquePtr<kind, T[], typename std::enable_if<!std::is_trivially_destructible<T>::value>::type> : public CagedPtr<kind, T> {
134 public:
135     CagedUniquePtr() : CagedPtr<kind, T>() { }
136     
137     CagedUniquePtr(T* ptr, size_t count)
138         : CagedPtr<kind, T>(ptr)
139         , m_count(count)
140     {
141     }
142     
143     CagedUniquePtr(CagedUniquePtr&& ptr)
144         : CagedPtr<kind, T>(ptr.m_ptr)
145         , m_count(ptr.m_count)
146     {
147         ptr.clear();
148     }
149     
150     CagedUniquePtr(const CagedUniquePtr&) = delete;
151     
152     template<typename... Arguments>
153     static CagedUniquePtr create(size_t count, Arguments&&... arguments)
154     {
155         T* result = static_cast<T*>(Gigacage::mallocArray(kind, count, sizeof(T)));
156         while (count--)
157             new (result + count) T(std::forward<Arguments>(arguments)...);
158         return CagedUniquePtr(result, count);
159     }
160     
161     CagedUniquePtr& operator=(CagedUniquePtr&& ptr)
162     {
163         destroy();
164         this->m_ptr = ptr.m_ptr;
165         m_count = ptr.m_count;
166         ptr.clear();
167         return *this;
168     }
169     
170     CagedUniquePtr& operator=(const CagedUniquePtr&) = delete;
171     
172     ~CagedUniquePtr()
173     {
174         destroy();
175     }
176     
177     // FIXME: It's weird that we inherit CagedPtr::operator== and friends, which don't do anything
178     // about m_count. It "works" because pointer equality is enough so long as everything is sane, but
179     // it seems like a missed opportunity to assert things.
180     // https://bugs.webkit.org/show_bug.cgi?id=175541
181     
182 private:
183     void destroy()
184     {
185         if (!this->m_ptr)
186             return;
187         while (m_count--)
188             this->m_ptr[m_count].~T();
189         Gigacage::free(kind, this->m_ptr);
190     }
191     
192     void clear()
193     {
194         this->m_ptr = nullptr;
195         m_count = 0;
196     }
197     
198     size_t m_count { 0 };
199 };
200
201 } // namespace WTF
202
203 using WTF::CagedUniquePtr;
204