1 | // Copyright 2019 Google LLC |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #include "dap/typeof.h" |
16 | |
17 | #include <atomic> |
18 | #include <memory> |
19 | #include <vector> |
20 | |
21 | namespace { |
22 | |
23 | // TypeInfos owns all the dap::TypeInfo instances. |
24 | struct TypeInfos { |
25 | // get() returns the TypeInfos singleton pointer. |
26 | // TypeInfos is constructed with an internal reference count of 1. |
27 | static TypeInfos* get(); |
28 | |
29 | // reference() increments the TypeInfos reference count. |
30 | inline void reference() { |
31 | assert(refcount.load() > 0); |
32 | refcount++; |
33 | } |
34 | |
35 | // release() decrements the TypeInfos reference count. |
36 | // If the reference count becomes 0, then the TypeInfos is destructed. |
37 | inline void release() { |
38 | if (--refcount == 0) { |
39 | this->~TypeInfos(); |
40 | } |
41 | } |
42 | |
43 | struct NullTI : public dap::TypeInfo { |
44 | using null = dap::null; |
45 | inline std::string name() const override { return "null" ; } |
46 | inline size_t size() const override { return sizeof(null); } |
47 | inline size_t alignment() const override { return alignof(null); } |
48 | inline void construct(void* ptr) const override { new (ptr) null(); } |
49 | inline void copyConstruct(void* dst, const void* src) const override { |
50 | new (dst) null(*reinterpret_cast<const null*>(src)); |
51 | } |
52 | inline void destruct(void* ptr) const override { |
53 | reinterpret_cast<null*>(ptr)->~null(); |
54 | } |
55 | inline bool deserialize(const dap::Deserializer*, void*) const override { |
56 | return true; |
57 | } |
58 | inline bool serialize(dap::Serializer*, const void*) const override { |
59 | return true; |
60 | } |
61 | }; |
62 | |
63 | dap::BasicTypeInfo<dap::boolean> boolean = {"boolean" }; |
64 | dap::BasicTypeInfo<dap::string> string = {"string" }; |
65 | dap::BasicTypeInfo<dap::integer> integer = {"integer" }; |
66 | dap::BasicTypeInfo<dap::number> number = {"number" }; |
67 | dap::BasicTypeInfo<dap::object> object = {"object" }; |
68 | dap::BasicTypeInfo<dap::any> any = {"any" }; |
69 | NullTI null; |
70 | std::vector<std::unique_ptr<dap::TypeInfo>> types; |
71 | |
72 | private: |
73 | TypeInfos() = default; |
74 | ~TypeInfos() = default; |
75 | std::atomic<uint64_t> refcount = {1}; |
76 | }; |
77 | |
78 | // aligned_storage() is a replacement for std::aligned_storage that isn't busted |
79 | // on older versions of MSVC. |
80 | template <size_t SIZE, size_t ALIGNMENT> |
81 | struct aligned_storage { |
82 | struct alignas(ALIGNMENT) type { |
83 | unsigned char data[SIZE]; |
84 | }; |
85 | }; |
86 | |
87 | TypeInfos* TypeInfos::get() { |
88 | static aligned_storage<sizeof(TypeInfos), alignof(TypeInfos)>::type memory; |
89 | |
90 | struct Instance { |
91 | TypeInfos* ptr() { return reinterpret_cast<TypeInfos*>(memory.data); } |
92 | Instance() { new (ptr()) TypeInfos(); } |
93 | ~Instance() { ptr()->release(); } |
94 | }; |
95 | |
96 | static Instance instance; |
97 | return instance.ptr(); |
98 | } |
99 | |
100 | } // namespace |
101 | |
102 | namespace dap { |
103 | |
104 | const TypeInfo* TypeOf<boolean>::type() { |
105 | return &TypeInfos::get()->boolean; |
106 | } |
107 | |
108 | const TypeInfo* TypeOf<string>::type() { |
109 | return &TypeInfos::get()->string; |
110 | } |
111 | |
112 | const TypeInfo* TypeOf<integer>::type() { |
113 | return &TypeInfos::get()->integer; |
114 | } |
115 | |
116 | const TypeInfo* TypeOf<number>::type() { |
117 | return &TypeInfos::get()->number; |
118 | } |
119 | |
120 | const TypeInfo* TypeOf<object>::type() { |
121 | return &TypeInfos::get()->object; |
122 | } |
123 | |
124 | const TypeInfo* TypeOf<any>::type() { |
125 | return &TypeInfos::get()->any; |
126 | } |
127 | |
128 | const TypeInfo* TypeOf<null>::type() { |
129 | return &TypeInfos::get()->null; |
130 | } |
131 | |
132 | void TypeInfo::deleteOnExit(TypeInfo* ti) { |
133 | TypeInfos::get()->types.emplace_back(std::unique_ptr<TypeInfo>(ti)); |
134 | } |
135 | |
136 | void initialize() { |
137 | TypeInfos::get()->reference(); |
138 | } |
139 | |
140 | void terminate() { |
141 | TypeInfos::get()->release(); |
142 | } |
143 | |
144 | } // namespace dap |
145 | |