201ad4372df1030c69b26b1d535ea14d73e6458b
[WebKit-https.git] / Source / WTF / wtf / UniqueArray.h
1 /*
2  * Copyright (C) 2018 Yusuke Suzuki <utatane.tea@gmail.com>. 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/CheckedArithmetic.h>
29 #include <wtf/FastMalloc.h>
30 #include <wtf/Vector.h>
31
32 namespace WTF {
33
34 template<bool isTriviallyDestructible, typename T> struct UniqueArrayMaker;
35
36 template<typename T>
37 struct UniqueArrayMaker<true, T> {
38     using ResultType = typename std::unique_ptr<T[], FastFree<T[]>>;
39
40     static ResultType make(size_t size)
41     {
42         // C++ `new T[N]` stores its `N` to somewhere. Otherwise, `delete []` cannot destroy
43         // these N elements. But we do not want to increase the size of allocated memory.
44         // If it is acceptable, we can just use Vector<T> instead. So this UniqueArray<T> only
45         // accepts the type T which has a trivial destructor. This allows us to skip calling
46         // destructors for N elements. And this allows UniqueArray<T> not to store its N size.
47         static_assert(std::is_trivially_destructible<T>::value, "");
48
49         // Do not use placement new like `new (storage) T[size]()`. `new T[size]()` requires
50         // larger storage than the `sizeof(T) * size` storage since it want to store `size`
51         // to somewhere.
52         T* storage = static_cast<T*>(fastMalloc((Checked<size_t>(sizeof(T)) * size).unsafeGet()));
53         VectorTypeOperations<T>::forceInitialize(storage, storage + size);
54         return ResultType(storage);
55     }
56 };
57
58 template<typename T>
59 struct UniqueArrayMaker<false, T> {
60     // Since we do not know how to store/retrieve N size to/from allocated memory when calling new [] and delete [],
61     // we use new [] and delete [] operators simply. We create UniqueArrayElement container for the type T.
62     // UniqueArrayElement has new [] and delete [] operators for FastMalloc. We allocate UniqueArrayElement[] and cast
63     // it to T[]. When deleting, the custom deleter casts T[] to UniqueArrayElement[] and deletes it.
64     class UniqueArrayElement {
65         WTF_MAKE_FAST_ALLOCATED;
66     public:
67         struct Deleter {
68             void operator()(T* pointer)
69             {
70                 delete [] bitwise_cast<UniqueArrayElement*>(pointer);
71             };
72         };
73
74         UniqueArrayElement() = default;
75
76         T value { };
77     };
78     static_assert(sizeof(T) == sizeof(UniqueArrayElement), "");
79
80     using ResultType = typename std::unique_ptr<T[], typename UniqueArrayElement::Deleter>;
81
82     static ResultType make(size_t size)
83     {
84         return ResultType(bitwise_cast<T*>(new UniqueArrayElement[size]()));
85     }
86 };
87
88 template<typename T>
89 using UniqueArray = typename UniqueArrayMaker<std::is_trivially_destructible<T>::value, T>::ResultType;
90
91 template<typename T>
92 UniqueArray<T> makeUniqueArray(size_t size)
93 {
94     static_assert(std::is_same<typename std::remove_extent<T>::type, T>::value, "");
95     return UniqueArrayMaker<std::is_trivially_destructible<T>::value, T>::make(size);
96 }
97
98 } // namespace WTF
99
100 using WTF::UniqueArray;
101 using WTF::makeUniqueArray;