// 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 #include #include #include #include namespace vk { namespace dbg { // Variable is a named value. struct Variable { std::string name; std::shared_ptr value; }; // VariableContainer is a collection of named values. class VariableContainer : public Value { public: using ID = dbg::ID; 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 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 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); // extend() adds base to the list of VariableContainers that will be // searched and traversed for variables. inline void extend(const std::shared_ptr &base); // The unique identifier of the variable. const ID id; private: struct ForeachIndex { size_t start; size_t count; }; template inline void foreach(ForeachIndex &index, const F &cb) const; inline std::shared_ptr type() const override; inline const void *get() const override; mutable std::mutex mutex; std::vector variables; std::unordered_map indices; std::vector> extends; }; VariableContainer::VariableContainer(ID id) : id(id) {} template void VariableContainer::foreach(size_t startIndex, size_t count, const F &cb) const { auto index = ForeachIndex{ startIndex, count }; foreach(index, cb); } template void VariableContainer::foreach(ForeachIndex &index, const F &cb) const { std::unique_lock 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 bool VariableContainer::find(const std::string &name, const F &cb) const { std::unique_lock 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 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) { put({ name, value }); } void VariableContainer::extend(const std::shared_ptr &base) { std::unique_lock lock(mutex); extends.emplace_back(base); } std::shared_ptr VariableContainer::type() const { return TypeOf::get(); } const void *VariableContainer::get() const { return nullptr; } } // namespace dbg } // namespace vk #endif // VK_DEBUG_VARIABLE_HPP_