Listing the "Blender Foundation" as copyright holder implied the Blender Foundation holds copyright to files which may include work from many developers. While keeping copyright on headers makes sense for isolated libraries, Blender's own code may be refactored or moved between files in a way that makes the per file copyright holders less meaningful. Copyright references to the "Blender Foundation" have been replaced with "Blender Authors", with the exception of `./extern/` since these this contains libraries which are more isolated, any changed to license headers there can be handled on a case-by-case basis. Some directories in `./intern/` have also been excluded: - `./intern/cycles/` it's own `AUTHORS` file is planned. - `./intern/opensubdiv/`. An "AUTHORS" file has been added, using the chromium projects authors file as a template. Design task: #110784 Ref !110783.
132 lines
3.2 KiB
C++
132 lines
3.2 KiB
C++
/* SPDX-FileCopyrightText: 2022 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup depsgraph
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "BLI_utildefines.h"
|
|
#include "BLI_vector.hh"
|
|
|
|
struct ID;
|
|
struct bConstraint;
|
|
struct bPoseChannel;
|
|
struct ModifierData;
|
|
|
|
namespace blender::deg {
|
|
|
|
/* This class keeps track of the builder calls nesting, allowing to unroll them back and provide a
|
|
* clue about how the builder made it to its current state.
|
|
*
|
|
* The tracing is based on the builder giving a trace clues to the stack. Typical usage is:
|
|
*
|
|
* void DepsgraphRelationBuilder::my_id_builder(ID *id)
|
|
* {
|
|
* if (built_map_.checkIsBuiltAndTag(id)) {
|
|
* return;
|
|
* }
|
|
*
|
|
* const BuilderStack::ScopedEntry stack_entry = stack_.trace(*id);
|
|
*
|
|
* ...
|
|
* }
|
|
*/
|
|
class BuilderStack {
|
|
public:
|
|
/* Entry of the backtrace.
|
|
* A cheap-to-construct wrapper which allows to gather a proper string representation whenever
|
|
* the stack is printed. */
|
|
class Entry {
|
|
public:
|
|
explicit Entry(const ID &id) : id_(&id) {}
|
|
|
|
explicit Entry(const bConstraint &constraint) : constraint_(&constraint) {}
|
|
|
|
explicit Entry(const bPoseChannel &pchan) : pchan_(&pchan) {}
|
|
|
|
explicit Entry(const ModifierData &modifier_data) : modifier_data_(&modifier_data) {}
|
|
|
|
private:
|
|
friend class BuilderStack;
|
|
|
|
const ID *id_ = nullptr;
|
|
const bConstraint *constraint_ = nullptr;
|
|
const ModifierData *modifier_data_ = nullptr;
|
|
const bPoseChannel *pchan_ = nullptr;
|
|
};
|
|
|
|
using Stack = Vector<Entry>;
|
|
|
|
/* A helper class to provide a RAII style of tracing. It is constructed by the
|
|
* `BuilderStack::trace` (which pushes entry to the stack), and upon destruction of this object
|
|
* the corresponding entry is popped from the stack.
|
|
*
|
|
* The goal of this `ScopedEntry` is to free developers from worrying about removing entries from
|
|
* the stack whenever leaving a builder step scope. */
|
|
class ScopedEntry {
|
|
public:
|
|
/* Delete copy constructor and operator: scoped entries are only supposed to be constructed
|
|
* once and never copied. */
|
|
ScopedEntry(const ScopedEntry &other) = delete;
|
|
ScopedEntry &operator=(const ScopedEntry &other) = delete;
|
|
|
|
/* Move semantic. */
|
|
ScopedEntry(ScopedEntry &&other) noexcept : stack_(other.stack_)
|
|
{
|
|
other.stack_ = nullptr;
|
|
}
|
|
ScopedEntry &operator=(ScopedEntry &&other)
|
|
{
|
|
if (this == &other) {
|
|
return *this;
|
|
}
|
|
|
|
stack_ = other.stack_;
|
|
other.stack_ = nullptr;
|
|
|
|
return *this;
|
|
}
|
|
|
|
~ScopedEntry()
|
|
{
|
|
/* Stack will become nullptr when the entry was moved somewhere else. */
|
|
if (stack_ != nullptr) {
|
|
BLI_assert(!stack_->is_empty());
|
|
stack_->pop_last();
|
|
}
|
|
}
|
|
|
|
private:
|
|
friend BuilderStack;
|
|
|
|
explicit ScopedEntry(Stack &stack) : stack_(&stack) {}
|
|
|
|
Stack *stack_;
|
|
};
|
|
|
|
BuilderStack() = default;
|
|
~BuilderStack() = default;
|
|
|
|
bool is_empty() const
|
|
{
|
|
return stack_.is_empty();
|
|
}
|
|
|
|
void print_backtrace(std::ostream &stream);
|
|
|
|
template<class... Args> ScopedEntry trace(const Args &...args)
|
|
{
|
|
stack_.append_as(args...);
|
|
|
|
return ScopedEntry(stack_);
|
|
}
|
|
|
|
private:
|
|
Stack stack_;
|
|
};
|
|
|
|
} // namespace blender::deg
|