mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-14 14:03:58 +00:00
Add a snapshot function to env_scoped_t
Allow creating lightweight read-only copies of a scoped environment.
This commit is contained in:
parent
0ca3ae7c7e
commit
64584a6624
2 changed files with 37 additions and 0 deletions
31
src/env.cpp
31
src/env.cpp
|
@ -305,6 +305,15 @@ struct var_stack_t {
|
|||
return var_stack_t(*this);
|
||||
}
|
||||
|
||||
/// Snapshot this vars_stack. That is, return a new vars_stack that has copies of all local
|
||||
/// variables. Note that this drops all shadowed nodes: only the currently executing function is
|
||||
/// copied. Global variables are referenced, not copied; this is both because there are a lot of
|
||||
/// global varibables so copying would be expensive, and some (electrics) are computed so cannot
|
||||
/// be effectively copied.
|
||||
std::unique_ptr<var_stack_t> snapshot() const {
|
||||
return make_unique<var_stack_t>(snapshot_node(top), global_env);
|
||||
}
|
||||
|
||||
/// \return true if the topomst local scope exports a variable.
|
||||
bool local_scope_exports(const env_node_ref_t &n) const;
|
||||
|
||||
|
@ -322,6 +331,24 @@ struct var_stack_t {
|
|||
|
||||
void get_exported(const env_node_t *n, var_table_t &h) const;
|
||||
|
||||
/// Recursive helper for snapshot(). Snapshot a node and its unshadows parents, returning it.
|
||||
env_node_ref_t snapshot_node(const env_node_ref_t &node) const {
|
||||
assert(node && "null node in snapshot_node");
|
||||
// If we are global, re-use the global node. If we reach a new scope, jump to globals; we
|
||||
// don't snapshot shadowed scopes, because the snapshot is intended to be read-only and so
|
||||
// there would be no way to access them.
|
||||
if (node == global_env) {
|
||||
return node;
|
||||
}
|
||||
auto next = snapshot_node(node->new_scope ? global_env : node->next);
|
||||
auto result = std::make_shared<env_node_t>(node->new_scope, next);
|
||||
// Copy over variables.
|
||||
// Note assigning env is a potentially big copy.
|
||||
result->exportv = node->exportv;
|
||||
result->env = node->env;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// \return the global variable set.
|
||||
/// Note that this is the only place where we talk about a single global variable set; each
|
||||
/// var_stack_t has its own reference to globals and could potentially have a different global
|
||||
|
@ -458,6 +485,10 @@ maybe_t<env_var_t> env_scoped_t::get(const wcstring &key, env_mode_flags_t mode)
|
|||
return none();
|
||||
}
|
||||
|
||||
std::shared_ptr<environment_t> env_scoped_t::snapshot() const {
|
||||
return std::shared_ptr<env_scoped_t>(new env_scoped_t(vars_->snapshot()));
|
||||
}
|
||||
|
||||
env_scoped_t::env_scoped_t() : env_scoped_t(var_stack_t::create()) {}
|
||||
env_scoped_t::env_scoped_t(std::unique_ptr<var_stack_t> vars) : vars_(std::move(vars)) {}
|
||||
env_scoped_t::env_scoped_t(env_scoped_t &&) = default;
|
||||
|
|
|
@ -216,6 +216,12 @@ class env_scoped_t : public environment_t {
|
|||
/// Returns all variable names.
|
||||
wcstring_list_t get_names(int flags) const override;
|
||||
|
||||
/// Snapshot this environment. This means returning a read-only copy. Local variables are copied
|
||||
/// but globals are shared (i.e. changes to global will be visible to this snapshot). This
|
||||
/// returns a shared_ptr for convenience, since the most common reason to snapshot is because
|
||||
/// you want to read from another thread.
|
||||
std::shared_ptr<environment_t> snapshot() const;
|
||||
|
||||
~env_scoped_t() override;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue