Flow 1.0.2
Flow project: Full implementation reference.
Public Member Functions | Private Attributes | List of all members
flow::util::Scoped_setter< Value > Class Template Reference

A simple RAII-pattern class template that, at construction, sets the specified location in memory to a specified value, memorizing the previous contents; and at destruction restores the value. More...

#include <util.hpp>

Collaboration diagram for flow::util::Scoped_setter< Value >:
[legend]

Public Member Functions

 Scoped_setter (Value *target, Value &&val_src_moved)
 Post-condition: *target contains was val_src_moved contained at ctor entry; and the destructor invocation shall reverse this, so that *target is restored to its value at entry. More...
 
 Scoped_setter (Scoped_setter &&src_moved)
 Move constructor: *this acts as src_moved would-have, while src_moved becomes a no-op object permanently. More...
 
 Scoped_setter (const Scoped_setter &)=delete
 Prohibit copying: for each explicit ctor invocation, there shall be exactly 1 non-no-op dtor invocation.
 
 ~Scoped_setter ()
 Restores *target (from main ctor) to its value at entry to said ctor; or does nothing if *this has been moved-from via the move ctor. More...
 
Scoped_setteroperator= (const Scoped_setter &)=delete
 Prohibit copying (see deleted copy ctor).
 
Scoped_setteroperator= (Scoped_setter &&)=delete
 Prohibit modifying existing *this; except that moving-from is enabled via the move ctor.
 

Private Attributes

Value * m_target_or_null
 Target object location; see ctors; if null then this is a moved-from Scoped_setter that intentionally no-ops. More...
 
Value m_saved_value
 If and only if m_target_or_null is non-null, this saves *m_target_or_null. Otherwise meaningless. More...
 

Detailed Description

template<typename Value>
class flow::util::Scoped_setter< Value >

A simple RAII-pattern class template that, at construction, sets the specified location in memory to a specified value, memorizing the previous contents; and at destruction restores the value.

E.g.:

thread_local int s_this_thread_val;
...
{
Scoped_setter<int> setter(&s_this_thread_val, 75); // Set it to 75 and memorize (whatever).
...
{
Scoped_setter<int> setter(&s_this_thread_val, 125); // Set it to 125 and memorize 75.
...
} // Restored from 125 to 75.
...
} // Restored from (probably) 75 to (whatever).
A simple RAII-pattern class template that, at construction, sets the specified location in memory to ...
Definition: util.hpp:120

The object is movable, not copyable (which is similar to unique_ptr) to prevent "double-restore." Related: one can easily return customized auto-setter/restorers:

thread_local Widget s_widget;
auto widget_setter_auto(Widget&& widget_moved)
{
return flow::util::Scoped_setter<Widget>(&s_widget, std::move(widget_moved));
}
...
{ // Later, some block: Set s_widget. Code here doesn't even know/care a Scoped_setter is involved.
const auto setter_auto = widget_setter_auto({ ...widget-init... });
...
} // Restore s_widget.

Thready safety

This is a simple object: it just performs a few assignments without any added concurrency protection. If the memory location can be accessed simultaneously by other threads, watch out.

In particular it's a good fit for thread-local locations: &X, where X is declared thread_local, or X == *(P.get()) where P is a boost::thread_specific_ptr.

Template Parameters
ValueThe stored type, which must be move-assignable and move-constructible. All Value writes are performed using exclusively these operations. Informally: For best performance when Value is a heavy-weight type, these operations should be be written to be light-weight, such as in terms of swapping a few scalars. In particular this is already the case for all STL-compliant container types.

Implementation

An alternative implementation, which could even be reduced to just an alias, would have used unique_ptr. However in this case I (ygoldfel) wanted maximum control for perf. The use case originally driving this was the thread-local verbosity override: log::Config::this_thread_verbosity_override_auto(). flow::log is fairly paranoid about performance, in general, although admittedly this particular call isn't necessarily ubiquitous.

Definition at line 119 of file util.hpp.

Constructor & Destructor Documentation

◆ Scoped_setter() [1/2]

template<typename Value >
flow::util::Scoped_setter< Value >::Scoped_setter ( Value *  target,
Value &&  val_src_moved 
)
explicit

Post-condition: *target contains was val_src_moved contained at ctor entry; and the destructor invocation shall reverse this, so that *target is restored to its value at entry.

*this cannot be copied, but it can be moved. As a result, it is guaranteed that the aforementioned destructor will execute exactly once; however it can be move-constructed-from-*this other Scope_setter's destructor, while our own dtor therefore is a no-op.

Parameters
targetThe target object that shall be set to val_src_moved now and restored in our, or moved-object's, dtor. The current value of *target is saved internally via assignment of move(*target). Behavior undefined (assertion may trip) if null.
val_src_movedValue to save to *target immediately, via assignment of move(val_src_moved).

Definition at line 181 of file util.hpp.

References flow::util::Scoped_setter< Value >::m_target_or_null.

◆ Scoped_setter() [2/2]

template<typename Value >
flow::util::Scoped_setter< Value >::Scoped_setter ( Scoped_setter< Value > &&  src_moved)

Move constructor: *this acts as src_moved would-have, while src_moved becomes a no-op object permanently.

Parameters
src_movedSource object. Its destructor shall do nothing after this returns.

Definition at line 189 of file util.hpp.

References flow::util::Scoped_setter< Value >::m_target_or_null.

◆ ~Scoped_setter()

template<typename Value >
flow::util::Scoped_setter< Value >::~Scoped_setter

Restores *target (from main ctor) to its value at entry to said ctor; or does nothing if *this has been moved-from via the move ctor.

Definition at line 200 of file util.hpp.

Member Data Documentation

◆ m_saved_value

template<typename Value >
Value flow::util::Scoped_setter< Value >::m_saved_value
private

If and only if m_target_or_null is non-null, this saves *m_target_or_null. Otherwise meaningless.

Definition at line 173 of file util.hpp.

◆ m_target_or_null

template<typename Value >
Value* flow::util::Scoped_setter< Value >::m_target_or_null
private

Target object location; see ctors; if null then this is a moved-from Scoped_setter that intentionally no-ops.

Definition at line 170 of file util.hpp.

Referenced by flow::util::Scoped_setter< Value >::Scoped_setter().


The documentation for this class was generated from the following file: