blob: 08e802d4c403ea53548cab9327c4568411ea5f58 [file] [log] [blame]
// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef VK_DEBUG_VARIABLE_HPP_
#define VK_DEBUG_VARIABLE_HPP_
#include "ID.hpp"
#include "Type.hpp"
#include "Value.hpp"
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
namespace vk {
namespace dbg {
// Variable is a named value.
struct Variable
{
std::string name;
std::shared_ptr<Value> value;
};
// VariableContainer is a collection of named values.
class VariableContainer : public Value
{
public:
using ID = dbg::ID<VariableContainer>;
inline VariableContainer(ID id);
// foreach() calls cb with each of the variables in the container.
// F must be a function with the signature void(const Variable&).
template<typename F>
inline void foreach(size_t startIndex, size_t count, const F &cb) const;
// find() looks up the variable with the given name.
// If the variable with the given name is found, cb is called with the
// variable and find() returns true.
template<typename F>
inline bool find(const std::string &name, const F &cb) const;
// put() places the variable var into the container.
inline void put(const Variable &var);
// put() places the variable with the given name and value into the container.
inline void put(const std::string &name, const std::shared_ptr<Value> &value);
// extend() adds base to the list of VariableContainers that will be
// searched and traversed for variables.
inline void extend(const std::shared_ptr<VariableContainer> &base);
// The unique identifier of the variable.
const ID id;
private:
struct ForeachIndex
{
size_t start;
size_t count;
};
template<typename F>
inline void foreach(ForeachIndex &index, const F &cb) const;
inline std::shared_ptr<Type> type() const override;
inline const void *get() const override;
mutable std::mutex mutex;
std::vector<Variable> variables;
std::unordered_map<std::string, int> indices;
std::vector<std::shared_ptr<VariableContainer>> extends;
};
VariableContainer::VariableContainer(ID id)
: id(id)
{}
template<typename F>
void VariableContainer::foreach(size_t startIndex, size_t count, const F &cb) const
{
auto index = ForeachIndex{ startIndex, count };
foreach(index, cb);
}
template<typename F>
void VariableContainer::foreach(ForeachIndex &index, const F &cb) const
{
std::unique_lock<std::mutex> lock(mutex);
for(size_t i = index.start; i < variables.size() && i < index.count; i++)
{
cb(variables[i]);
}
index.start -= std::min(index.start, variables.size());
index.count -= std::min(index.count, variables.size());
for(auto &base : extends)
{
base->foreach(index, cb);
}
}
template<typename F>
bool VariableContainer::find(const std::string &name, const F &cb) const
{
std::unique_lock<std::mutex> lock(mutex);
for(auto const &var : variables)
{
if(var.name == name)
{
cb(var);
return true;
}
}
for(auto &base : extends)
{
if(base->find(name, cb))
{
return true;
}
}
return false;
}
void VariableContainer::put(const Variable &var)
{
std::unique_lock<std::mutex> lock(mutex);
auto it = indices.find(var.name);
if(it == indices.end())
{
indices.emplace(var.name, variables.size());
variables.push_back(var);
}
else
{
variables[it->second].value = var.value;
}
}
void VariableContainer::put(const std::string &name,
const std::shared_ptr<Value> &value)
{
put({ name, value });
}
void VariableContainer::extend(const std::shared_ptr<VariableContainer> &base)
{
std::unique_lock<std::mutex> lock(mutex);
extends.emplace_back(base);
}
std::shared_ptr<Type> VariableContainer::type() const
{
return TypeOf<VariableContainer>::get();
}
const void *VariableContainer::get() const
{
return nullptr;
}
} // namespace dbg
} // namespace vk
#endif // VK_DEBUG_VARIABLE_HPP_