Command-Framework: enable the use of immutable types as state memento
This commit is contained in:
parent
c799c7644c
commit
edcf503da1
6 changed files with 32 additions and 13 deletions
|
|
@ -55,8 +55,8 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifndef LIB_REPLACABLE_ITEM_H
|
||||
#define LIB_REPLACABLE_ITEM_H
|
||||
#ifndef LIB_REPLACEABLE_ITEM_H
|
||||
#define LIB_REPLACEABLE_ITEM_H
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/null-value.hpp"
|
||||
|
|
@ -237,4 +237,4 @@ namespace wrapper {
|
|||
|
||||
|
||||
}} // namespace lib::wrap
|
||||
#endif /*LIB_REPLACABLE_ITEM_H*/
|
||||
#endif /*LIB_REPLACEABLE_ITEM_H*/
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "lib/meta/maybe-compare.hpp"
|
||||
#include "lib/meta/function-closure.hpp"
|
||||
#include "proc/control/command-signature.hpp"
|
||||
#include "lib/replaceable-item.hpp"
|
||||
#include "lib/functor-util.hpp"
|
||||
#include "lib/format-obj.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
|
@ -60,6 +61,7 @@ namespace control {
|
|||
using lib::meta::func::bindLast;
|
||||
using lib::meta::func::chained;
|
||||
using lib::meta::equals_safeInvoke;
|
||||
using lib::wrapper::ReplaceableItem;
|
||||
|
||||
LUMIERA_ERROR_DECLARE (MISSING_MEMENTO); ///< Undo functor not yet usable, because no undo state has been captured
|
||||
|
||||
|
|
@ -80,7 +82,7 @@ namespace control {
|
|||
* to be provided with a reference to this stored memento value through an additional
|
||||
* parameter (which by convention is always the last argument of the undo function).
|
||||
* @warning take care of the MementoTie storage location, as the bound functions
|
||||
* returned by #tieCaptureFunc and #tieUndoFunc refer to \c this internally.
|
||||
* returned by #tieCaptureFunc and #tieUndoFunc refer to `this` implicitly.
|
||||
*
|
||||
* @param SIG signature of the command operation
|
||||
* @param MEM type of the memento state to capture. Needs to be default constructible and copyable
|
||||
|
|
@ -94,7 +96,7 @@ namespace control {
|
|||
typedef typename CommandSignature<SIG,MEM>::CaptureSig SIG_cap;
|
||||
typedef typename CommandSignature<SIG,MEM>::UndoOp_Sig SIG_undo;
|
||||
|
||||
MEM memento_; ///< storage holding the captured state for undo
|
||||
ReplaceableItem<MEM> memento_; ///< storage holding the captured state for undo
|
||||
|
||||
bool isCaptured_;
|
||||
|
||||
|
|
@ -214,7 +216,7 @@ namespace control {
|
|||
return "<mem:missing>";
|
||||
|
||||
return "<mem: "
|
||||
+ util::toString (memento_)
|
||||
+ util::toString (memento_.get())
|
||||
+ ">";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,19 @@ namespace test {
|
|||
template<typename TY>
|
||||
int Tracker<TY>::instanceCnt (0);
|
||||
|
||||
/** prepare a (singleton) _empty value_ for the memento.
|
||||
* @remarks This is done prior to observing the Tracker instanceCnt,
|
||||
* because this empty value obviously remains allocated forever.
|
||||
* The memento is stored within a [special holder](\ref lib::ReplaceableItem)
|
||||
* to allow capturing memento state even from immutable values, which only can
|
||||
* be copy constructed. This mechanism uses lib::NullValue to retrieve an
|
||||
* empty placeholder value when the memento has not yet been captured.
|
||||
*/
|
||||
void
|
||||
prepareEmptyMemento()
|
||||
{
|
||||
lib::NullValue<Tracker<string>>::get();
|
||||
}
|
||||
|
||||
/** Dummy custom memento datatype
|
||||
* @note memento needs to be equality comparable
|
||||
|
|
@ -191,6 +204,7 @@ namespace test {
|
|||
run (Arg)
|
||||
{
|
||||
ArgTuples testTuples;
|
||||
prepareEmptyMemento();
|
||||
Tracker<TimeVar>::instanceCnt = 0;
|
||||
Tracker<string>::instanceCnt = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ namespace test {
|
|||
using lib::time::Time;
|
||||
using lib::time::TimeVar;
|
||||
using lib::time::TimeValue;
|
||||
using lib::time::Offset;
|
||||
|
||||
|
||||
|
||||
|
|
@ -53,14 +54,14 @@ namespace test {
|
|||
*dummyObj += TimeValue(randVal);
|
||||
}
|
||||
|
||||
TimeVar
|
||||
Offset
|
||||
capture (P<TimeVar> dummyObj, int)
|
||||
{
|
||||
return *dummyObj;
|
||||
return Offset{*dummyObj};
|
||||
}
|
||||
|
||||
void
|
||||
undoIt (P<TimeVar> dummyObj, int, TimeVar oldVal)
|
||||
undoIt (P<TimeVar> dummyObj, int, Offset oldVal)
|
||||
{
|
||||
*dummyObj = oldVal;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,14 +54,14 @@ namespace test {
|
|||
implicitTestState += dur;
|
||||
}
|
||||
|
||||
TimeVar
|
||||
Time
|
||||
capture (Duration)
|
||||
{
|
||||
return implicitTestState;
|
||||
}
|
||||
|
||||
void
|
||||
undoIt (Duration, TimeVar oldVal)
|
||||
undoIt (Duration, Time oldVal)
|
||||
{
|
||||
implicitTestState = oldVal;
|
||||
}
|
||||
|
|
@ -81,6 +81,8 @@ namespace test {
|
|||
* - we support immutable argument types, which means the command binding
|
||||
* machinery works without (re)assignment, only copy construction of
|
||||
* argument holders into an inline buffer.
|
||||
* - likewise we support to use an immutable type as captured state
|
||||
* memento, which is demonstrated by capturing a Time value
|
||||
*
|
||||
* @see BusTerm_test
|
||||
* @see TupleRecordInit_test
|
||||
|
|
|
|||
|
|
@ -77,14 +77,14 @@ namespace test {
|
|||
testCommandState += Offset(dur) + offset*factor;
|
||||
}
|
||||
|
||||
string
|
||||
Time
|
||||
capture (Duration, Offset, int)
|
||||
{
|
||||
return testCommandState;
|
||||
}
|
||||
|
||||
void
|
||||
undoIt (Duration, Offset, int, string oldState)
|
||||
undoIt (Duration, Offset, int, Time oldState)
|
||||
{
|
||||
// dummyState = oldState;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue