• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
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 //    http://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 #ifndef VK_DEBUG_VARIABLE_HPP_
16 #define VK_DEBUG_VARIABLE_HPP_
17 
18 #include "ID.hpp"
19 #include "Type.hpp"
20 #include "Value.hpp"
21 
22 #include <memory>
23 #include <mutex>
24 #include <string>
25 #include <unordered_map>
26 #include <vector>
27 
28 namespace vk {
29 namespace dbg {
30 
31 // Variable is a named value.
32 struct Variable
33 {
34 	std::string name;
35 	std::shared_ptr<Value> value;
36 };
37 
38 // VariableContainer is a collection of named values.
39 class VariableContainer : public Value
40 {
41 public:
42 	using ID = dbg::ID<VariableContainer>;
43 
44 	inline VariableContainer(ID id);
45 
46 	// foreach() calls cb with each of the variables in the container.
47 	// F must be a function with the signature void(const Variable&).
48 	template<typename F>
49 	inline void foreach(size_t startIndex, size_t count, const F &cb) const;
50 
51 	// find() looks up the variable with the given name.
52 	// If the variable with the given name is found, cb is called with the
53 	// variable and find() returns true.
54 	template<typename F>
55 	inline bool find(const std::string &name, const F &cb) const;
56 
57 	// put() places the variable var into the container.
58 	inline void put(const Variable &var);
59 
60 	// put() places the variable with the given name and value into the container.
61 	inline void put(const std::string &name, const std::shared_ptr<Value> &value);
62 
63 	// extend() adds base to the list of VariableContainers that will be
64 	// searched and traversed for variables.
65 	inline void extend(const std::shared_ptr<VariableContainer> &base);
66 
67 	// The unique identifier of the variable.
68 	const ID id;
69 
70 private:
71 	struct ForeachIndex
72 	{
73 		size_t start;
74 		size_t count;
75 	};
76 
77 	template<typename F>
78 	inline void foreach(ForeachIndex &index, const F &cb) const;
79 
80 	inline std::shared_ptr<Type> type() const override;
81 	inline const void *get() const override;
82 
83 	mutable std::mutex mutex;
84 	std::vector<Variable> variables;
85 	std::unordered_map<std::string, int> indices;
86 	std::vector<std::shared_ptr<VariableContainer>> extends;
87 };
88 
VariableContainer(ID id)89 VariableContainer::VariableContainer(ID id)
90     : id(id)
91 {}
92 
93 template<typename F>
foreach(size_t startIndex,size_t count,const F & cb) const94 void VariableContainer::foreach(size_t startIndex, size_t count, const F &cb) const
95 {
96 	auto index = ForeachIndex{ startIndex, count };
97 	foreach(index, cb);
98 }
99 
100 template<typename F>
foreach(ForeachIndex & index,const F & cb) const101 void VariableContainer::foreach(ForeachIndex &index, const F &cb) const
102 {
103 	std::unique_lock<std::mutex> lock(mutex);
104 	for(size_t i = index.start; i < variables.size() && i < index.count; i++)
105 	{
106 		cb(variables[i]);
107 	}
108 
109 	index.start -= std::min(index.start, variables.size());
110 	index.count -= std::min(index.count, variables.size());
111 
112 	for(auto &base : extends)
113 	{
114 		base->foreach(index, cb);
115 	}
116 }
117 
118 template<typename F>
find(const std::string & name,const F & cb) const119 bool VariableContainer::find(const std::string &name, const F &cb) const
120 {
121 	std::unique_lock<std::mutex> lock(mutex);
122 	for(auto const &var : variables)
123 	{
124 		if(var.name == name)
125 		{
126 			cb(var);
127 			return true;
128 		}
129 	}
130 	for(auto &base : extends)
131 	{
132 		if(base->find(name, cb))
133 		{
134 			return true;
135 		}
136 	}
137 	return false;
138 }
139 
put(const Variable & var)140 void VariableContainer::put(const Variable &var)
141 {
142 	std::unique_lock<std::mutex> lock(mutex);
143 	auto it = indices.find(var.name);
144 	if(it == indices.end())
145 	{
146 		indices.emplace(var.name, variables.size());
147 		variables.push_back(var);
148 	}
149 	else
150 	{
151 		variables[it->second].value = var.value;
152 	}
153 }
154 
put(const std::string & name,const std::shared_ptr<Value> & value)155 void VariableContainer::put(const std::string &name,
156                             const std::shared_ptr<Value> &value)
157 {
158 	put({ name, value });
159 }
160 
extend(const std::shared_ptr<VariableContainer> & base)161 void VariableContainer::extend(const std::shared_ptr<VariableContainer> &base)
162 {
163 	std::unique_lock<std::mutex> lock(mutex);
164 	extends.emplace_back(base);
165 }
166 
type() const167 std::shared_ptr<Type> VariableContainer::type() const
168 {
169 	return TypeOf<VariableContainer>::get();
170 }
171 
get() const172 const void *VariableContainer::get() const
173 {
174 	return nullptr;
175 }
176 
177 }  // namespace dbg
178 }  // namespace vk
179 
180 #endif  // VK_DEBUG_VARIABLE_HPP_