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
21namespace {
22
23// TypeInfos owns all the dap::TypeInfo instances.
24struct 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.
80template <size_t SIZE, size_t ALIGNMENT>
81struct aligned_storage {
82 struct alignas(ALIGNMENT) type {
83 unsigned char data[SIZE];
84 };
85};
86
87TypeInfos* 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
102namespace dap {
103
104const TypeInfo* TypeOf<boolean>::type() {
105 return &TypeInfos::get()->boolean;
106}
107
108const TypeInfo* TypeOf<string>::type() {
109 return &TypeInfos::get()->string;
110}
111
112const TypeInfo* TypeOf<integer>::type() {
113 return &TypeInfos::get()->integer;
114}
115
116const TypeInfo* TypeOf<number>::type() {
117 return &TypeInfos::get()->number;
118}
119
120const TypeInfo* TypeOf<object>::type() {
121 return &TypeInfos::get()->object;
122}
123
124const TypeInfo* TypeOf<any>::type() {
125 return &TypeInfos::get()->any;
126}
127
128const TypeInfo* TypeOf<null>::type() {
129 return &TypeInfos::get()->null;
130}
131
132void TypeInfo::deleteOnExit(TypeInfo* ti) {
133 TypeInfos::get()->types.emplace_back(std::unique_ptr<TypeInfo>(ti));
134}
135
136void initialize() {
137 TypeInfos::get()->reference();
138}
139
140void terminate() {
141 TypeInfos::get()->release();
142}
143
144} // namespace dap
145