• 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 "Value.hpp"
20 
21 #include "System/Debug.hpp"
22 
23 #include "marl/mutex.h"
24 #include "marl/tsa.h"
25 
26 #include <algorithm>
27 #include <atomic>
28 #include <limits>
29 #include <memory>
30 #include <string>
31 #include <unordered_map>
32 #include <vector>
33 
34 namespace vk {
35 namespace dbg {
36 
37 // Variable is a named value.
38 struct Variable
39 {
40 	std::string name;
41 	std::shared_ptr<Value> value;
42 
43 	// operator bool returns true iff value is not nullptr.
operator boolvk::dbg::Variable44 	operator bool() const { return value != nullptr; }
45 };
46 
47 // Variables is an interface to a collection of named values.
48 class Variables
49 {
50 public:
51 	using ID = dbg::ID<Variables>;
52 
53 	using ForeachCallback = std::function<bool(const Variable &)>;
54 	using FindCallback = std::function<void(const Variable &)>;
55 
56 	inline Variables();
57 	virtual ~Variables();
58 
59 	// foreach() calls cb with each of the variables in the container, while cb
60 	// returns true.
61 	// foreach() will return when cb returns false.
62 	inline void foreach(const ForeachCallback &cb);
63 
64 	// foreach() calls cb with each of the variables in the container within the
65 	// indexed range: [startIndex, startIndex+count), while cb returns true.
66 	// foreach() will return when cb returns false.
67 	virtual void foreach(size_t startIndex, size_t count, const ForeachCallback &cb) = 0;
68 
69 	// get() looks up and returns the variable with the given name.
70 	virtual std::shared_ptr<Value> get(const std::string &name);
71 
72 	// string() returns the list of variables formatted to a string using the
73 	// given flags.
74 	virtual std::string string(const FormatFlags &fmt /* = FormatFlags::Default */);
75 
76 	// The unique identifier of the variables.
77 	const ID id;
78 
79 private:
80 	static std::atomic<int> nextID;
81 };
82 
Variables()83 Variables::Variables()
84     : id(nextID++)
85 {}
86 
foreach(const ForeachCallback & cb)87 void Variables::foreach(const ForeachCallback &cb)
88 {
89 	foreach(0, std::numeric_limits<size_t>::max(), cb);
90 }
91 
92 // VariableContainer is mutable collection of named values.
93 class VariableContainer : public Variables
94 {
95 public:
96 	using ID = dbg::ID<VariableContainer>;
97 
98 	inline void foreach(size_t startIndex, size_t count, const ForeachCallback &cb) override;
99 	inline std::shared_ptr<Value> get(const std::string &name) override;
100 
101 	// put() places the variable var into the container.
102 	inline void put(const Variable &var);
103 
104 	// put() places the variable with the given name and value into the container.
105 	inline void put(const std::string &name, const std::shared_ptr<Value> &value);
106 
107 	// extend() adds base to the list of Variables that will be searched and
108 	// traversed for variables after those in this VariableContainer are
109 	// searched / traversed.
110 	inline void extend(const std::shared_ptr<Variables> &base);
111 
112 private:
113 	struct ForeachIndex
114 	{
115 		size_t start;
116 		size_t count;
117 	};
118 
119 	template<typename F>
120 	inline void foreach(ForeachIndex &index, const F &cb);
121 
122 	mutable marl::mutex mutex;
123 	std::vector<Variable> variables GUARDED_BY(mutex);
124 	std::unordered_map<std::string, int> indices GUARDED_BY(mutex);
125 	std::vector<std::shared_ptr<Variables>> extends GUARDED_BY(mutex);
126 };
127 
foreach(size_t startIndex,size_t count,const ForeachCallback & cb)128 void VariableContainer::foreach(size_t startIndex, size_t count, const ForeachCallback &cb)
129 {
130 	auto index = ForeachIndex{ startIndex, count };
131 	foreach(index, cb);
132 }
133 
134 template<typename F>
foreach(ForeachIndex & index,const F & cb)135 void VariableContainer::foreach(ForeachIndex &index, const F &cb)
136 {
137 	marl::lock lock(mutex);
138 	for(size_t i = index.start; i < variables.size() && i < index.count; i++)
139 	{
140 		if(!cb(variables[i]))
141 		{
142 			return;
143 		}
144 	}
145 
146 	index.start -= std::min(index.start, variables.size());
147 	index.count -= std::min(index.count, variables.size());
148 
149 	for(auto &base : extends)
150 	{
151 		base->foreach(index.start, index.count, cb);
152 	}
153 }
154 
get(const std::string & name)155 std::shared_ptr<Value> VariableContainer::get(const std::string &name)
156 {
157 	marl::lock lock(mutex);
158 	for(auto const &var : variables)
159 	{
160 		if(var.name == name)
161 		{
162 			return var.value;
163 		}
164 	}
165 	for(auto &base : extends)
166 	{
167 		if(auto val = base->get(name))
168 		{
169 			return val;
170 		}
171 	}
172 	return nullptr;
173 }
174 
put(const Variable & var)175 void VariableContainer::put(const Variable &var)
176 {
177 	ASSERT(var.value);
178 
179 	marl::lock lock(mutex);
180 	auto it = indices.find(var.name);
181 	if(it == indices.end())
182 	{
183 		indices.emplace(var.name, variables.size());
184 		variables.push_back(var);
185 	}
186 	else
187 	{
188 		variables[it->second].value = var.value;
189 	}
190 }
191 
put(const std::string & name,const std::shared_ptr<Value> & value)192 void VariableContainer::put(const std::string &name,
193                             const std::shared_ptr<Value> &value)
194 {
195 	put({ name, value });
196 }
197 
extend(const std::shared_ptr<Variables> & base)198 void VariableContainer::extend(const std::shared_ptr<Variables> &base)
199 {
200 	marl::lock lock(mutex);
201 	extends.emplace_back(base);
202 }
203 
204 }  // namespace dbg
205 }  // namespace vk
206 
207 #endif  // VK_DEBUG_VARIABLE_HPP_
208