3 ms·
With RAII, it is not terribly hard to build dynamic scoping on top of thread_local variables in C++. template<class T> struct scoped_replace { sco
by gpderetta 2y ago
With RAII, it is not terribly hard to build dynamic scoping on top of thread_local variables in C++.
template<class T>
struct scoped_replace {
scoped_replace(T& ref, T new_val)
: ref(ref), old_val(ref) {
ref = std::move(new_val);
}
~scoped_replace() { ref = std::move(old_val); }
T& ref;
T old_val;
};
thread_local int val = 0;
int foo() {
return val;
}
int bar() {
scoped_replace _(val, 42);
return foo();
}
int main() {
foo(); // returns 0
bar(); // returns 42;
foo(); // still returns 0
}
- kazinator 2y agoThat's a "shallow binding" implementation of dynamic scope which works fine enough; but if you have coroutines and continuations and such, it might not play along. Whichever thread invokes a continuation will see its own current value of the variable. Under "deep binding", where we have a dynamic environment stack, we can save that stack as part of the context of the coroutine, continuation or whatever else. It requires only one word: a pointer to the top of the dynamic environment. Whenever we restore that pointer value, we have the original environment.