The table head of test freshness page should not scroll with the page.
[WebKit-https.git] / Source / WTF / wtf / PoisonedUniquePtr.h
1 /*
2  * Copyright (C) 2017-2018 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include <cstddef>
29 #include <memory>
30 #include <wtf/FastMalloc.h>
31 #include <wtf/Poisoned.h>
32
33 namespace WTF {
34
35 template<typename Poison, typename T, typename Enable = void>
36 class PoisonedUniquePtr : public Poisoned<Poison, T*> {
37     WTF_MAKE_FAST_ALLOCATED;
38     using Base = Poisoned<Poison, T*>;
39 public:
40     static constexpr bool isPoisonedUniquePtrType = true;
41     using ValueType = T;
42
43     PoisonedUniquePtr() = default;
44     PoisonedUniquePtr(std::nullptr_t) : Base() { }
45     PoisonedUniquePtr(T* ptr) : Base(ptr) { }
46     PoisonedUniquePtr(PoisonedUniquePtr&& ptr) : Base(WTFMove(ptr)) { ptr.clearWithoutDestroy(); }
47     PoisonedUniquePtr(std::unique_ptr<T>&& unique) : PoisonedUniquePtr(unique.release()) { }
48
49     template<typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>>
50     PoisonedUniquePtr(std::unique_ptr<U>&& unique)
51         : Base(unique.release())
52     { }
53
54     template<typename Other, typename = std::enable_if_t<Other::isPoisonedUniquePtrType && std::is_base_of<T, typename Other::ValueType>::value>>
55     PoisonedUniquePtr(Other&& ptr)
56         : Base(ptr.unpoisoned())
57     {
58         ptr.clearWithoutDestroy();
59     }
60
61     PoisonedUniquePtr(const PoisonedUniquePtr&) = delete;
62
63     ~PoisonedUniquePtr() { destroy(); }
64
65     template<typename... Arguments>
66     static PoisonedUniquePtr create(Arguments&&... arguments)
67     {
68         return new T(std::forward<Arguments>(arguments)...);
69     }
70
71     PoisonedUniquePtr& operator=(T* ptr)
72     {
73         if (LIKELY(this->unpoisoned() != ptr)) {
74             this->clear();
75             this->Base::operator=(ptr);
76         }
77         return *this;
78     }
79
80     PoisonedUniquePtr& operator=(std::unique_ptr<T>&& unique)
81     {
82         this->clear();
83         this->Base::operator=(unique.release());
84         return *this;
85     }
86
87     template<typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>>
88     PoisonedUniquePtr& operator=(std::unique_ptr<U>&& unique)
89     {
90         this->clear();
91         this->Base::operator=(unique.release());
92         return *this;
93     }
94
95     template<typename Other, typename = std::enable_if_t<Other::isPoisonedUniquePtrType && std::is_base_of<T, typename Other::ValueType>::value>>
96     PoisonedUniquePtr& operator=(Other&& ptr)
97     {
98         ASSERT(this == static_cast<void*>(&ptr) || this->unpoisoned() != ptr.unpoisoned());
99         if (LIKELY(this != static_cast<void*>(&ptr))) {
100             this->clear();
101             this->Base::operator=(WTFMove(ptr));
102             ptr.clearWithoutDestroy();
103         }
104         return *this;
105     }
106
107     PoisonedUniquePtr& operator=(const PoisonedUniquePtr&) = delete;
108
109     T* get() const { return this->unpoisoned(); }
110     T& operator[](size_t index) const { return this->unpoisoned()[index]; }
111
112     void clear()
113     {
114         destroy();
115         clearWithoutDestroy();
116     }
117
118 private:
119     void destroy()
120     {
121         if (!this->bits())
122             return;
123         delete this->unpoisoned();
124     }
125
126     void clearWithoutDestroy() { Base::clear(); }
127
128     template<typename, typename, typename> friend class PoisonedUniquePtr;
129 };
130
131 template<typename Poison, typename T>
132 class PoisonedUniquePtr<Poison, T[]> : public Poisoned<Poison, T*> {
133     WTF_MAKE_FAST_ALLOCATED;
134     using Base = Poisoned<Poison, T*>;
135 public:
136     static constexpr bool isPoisonedUniquePtrType = true;
137     using ValueType = T[];
138
139     PoisonedUniquePtr() = default;
140     PoisonedUniquePtr(std::nullptr_t) : Base() { }
141     PoisonedUniquePtr(T* ptr) : Base(ptr) { }
142     PoisonedUniquePtr(PoisonedUniquePtr&& ptr) : Base(WTFMove(ptr)) { ptr.clearWithoutDestroy(); }
143     PoisonedUniquePtr(std::unique_ptr<T[]>&& unique) : PoisonedUniquePtr(unique.release()) { }
144
145     template<typename Other, typename = std::enable_if_t<Other::isPoisonedUniquePtrType && std::is_same<T[], typename Other::ValueType>::value>>
146     PoisonedUniquePtr(Other&& ptr)
147         : Base(ptr.unpoisoned())
148     {
149         ptr.clearWithoutDestroy();
150     }
151
152     PoisonedUniquePtr(const PoisonedUniquePtr&) = delete;
153
154     ~PoisonedUniquePtr() { destroy(); }
155
156     template<typename... Arguments>
157     static PoisonedUniquePtr create(size_t count, Arguments&&... arguments)
158     {
159         T* result = new T[count];
160         while (count--)
161             new (result + count) T(std::forward<Arguments>(arguments)...);
162         return result;
163     }
164
165     PoisonedUniquePtr& operator=(T* ptr)
166     {
167         if (LIKELY(this->unpoisoned() != ptr)) {
168             this->clear();
169             this->Base::operator=(ptr);
170         }
171         return *this;
172     }
173     
174     PoisonedUniquePtr& operator=(std::unique_ptr<T[]>&& unique)
175     {
176         this->clear();
177         this->Base::operator=(unique.release());
178         return *this;
179     }
180
181     template<typename Other, typename = std::enable_if_t<Other::isPoisonedUniquePtrType && std::is_same<T[], typename Other::ValueType>::value>>
182     PoisonedUniquePtr& operator=(Other&& ptr)
183     {
184         ASSERT(this == static_cast<void*>(&ptr) || this->unpoisoned() != ptr.unpoisoned());
185         if (LIKELY(this != static_cast<void*>(&ptr))) {
186             this->clear();
187             this->Base::operator=(WTFMove(ptr));
188             ptr.clearWithoutDestroy();
189         }
190         return *this;
191     }
192
193     PoisonedUniquePtr& operator=(const PoisonedUniquePtr&) = delete;
194
195     T* get() const { return this->unpoisoned(); }
196     T& operator[](size_t index) const { return this->unpoisoned()[index]; }
197
198     void clear()
199     {
200         destroy();
201         clearWithoutDestroy();
202     }
203
204 private:
205     void destroy()
206     {
207         if (!this->bits())
208             return;
209         delete[] this->unpoisoned();
210     }
211
212     void clearWithoutDestroy() { Base::clear(); }
213
214     template<typename, typename, typename> friend class PoisonedUniquePtr;
215 };
216
217 } // namespace WTF
218
219 using WTF::PoisonedUniquePtr;
220