]> git.saurik.com Git - apple/objc4.git/blob - runtime/DenseMapExtras.h
objc4-781.2.tar.gz
[apple/objc4.git] / runtime / DenseMapExtras.h
1 /*
2 * Copyright (c) 2019 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #ifndef DENSEMAPEXTRAS_H
25 #define DENSEMAPEXTRAS_H
26
27 #include "llvm-DenseMap.h"
28 #include "llvm-DenseSet.h"
29
30 namespace objc {
31
32 // We cannot use a C++ static initializer to initialize certain globals because
33 // libc calls us before our C++ initializers run. We also don't want a global
34 // pointer to some globals because of the extra indirection.
35 //
36 // ExplicitInit / LazyInit wrap doing it the hard way.
37 template <typename Type>
38 class ExplicitInit {
39 alignas(Type) uint8_t _storage[sizeof(Type)];
40
41 public:
42 template <typename... Ts>
43 void init(Ts &&... Args) {
44 new (_storage) Type(std::forward<Ts>(Args)...);
45 }
46
47 Type &get() {
48 return *reinterpret_cast<Type *>(_storage);
49 }
50 };
51
52 template <typename Type>
53 class LazyInit {
54 alignas(Type) uint8_t _storage[sizeof(Type)];
55 bool _didInit;
56
57 public:
58 template <typename... Ts>
59 Type *get(bool allowCreate, Ts &&... Args) {
60 if (!_didInit) {
61 if (!allowCreate) {
62 return nullptr;
63 }
64 new (_storage) Type(std::forward<Ts>(Args)...);
65 _didInit = true;
66 }
67 return reinterpret_cast<Type *>(_storage);
68 }
69 };
70
71 // Convenience class for Dense Maps & Sets
72 template <typename Key, typename Value>
73 class ExplicitInitDenseMap : public ExplicitInit<DenseMap<Key, Value>> { };
74
75 template <typename Key, typename Value>
76 class LazyInitDenseMap : public LazyInit<DenseMap<Key, Value>> { };
77
78 template <typename Value>
79 class ExplicitInitDenseSet : public ExplicitInit<DenseSet<Value>> { };
80
81 template <typename Value>
82 class LazyInitDenseSet : public LazyInit<DenseSet<Value>> { };
83
84 } // namespace objc
85
86 #endif /* DENSEMAPEXTRAS_H */