WIP draft of clone builder implementation
This commit is contained in:
parent
7812792f75
commit
bb7ff5e317
3 changed files with 66 additions and 112 deletions
|
|
@ -78,13 +78,11 @@ namespace control {
|
||||||
// : public lib::BoolCheckable<CommandImpl
|
// : public lib::BoolCheckable<CommandImpl
|
||||||
// , boost::noncopyable
|
// , boost::noncopyable
|
||||||
// >
|
// >
|
||||||
|
: public boost::noncopyable
|
||||||
{
|
{
|
||||||
Mutation do_;
|
TypedAllocationManager& allocator_;
|
||||||
UndoMutation undo_;
|
shared_ptr<CmdClosure> newClo_;
|
||||||
|
|
||||||
shared_ptr<CmdClosure> pClo_;
|
|
||||||
|
|
||||||
HandlingPattern::ID defaultPatt_;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename ARG>
|
template<typename ARG>
|
||||||
|
|
@ -101,115 +99,54 @@ namespace control {
|
||||||
#define _TY(_ID_) typename _Type<ARG>::_ID_
|
#define _TY(_ID_) typename _Type<ARG>::_ID_
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** build a new implementation frame, and do the initial wiring.
|
CommandImplCloneBuilder (TypedAllocationManager allo)
|
||||||
* On the interface the specific type is discarded afterwards.
|
: allocator_(allo)
|
||||||
* This information is still kept though, as encoded into the vtable
|
, newClo_()
|
||||||
* of the embedded FunErasure objects holding the command operation
|
|
||||||
* and undo functors, and the vtable of the embedded CmdClosure */
|
|
||||||
template<typename ARG>
|
|
||||||
CommandImpl (shared_ptr<ARG> pArgHolder
|
|
||||||
,_TY (Func_op) const& operFunctor
|
|
||||||
,_TY (Func_cap) const& captFunctor
|
|
||||||
,_TY (Func_undo) const& undoFunctor
|
|
||||||
)
|
|
||||||
: do_(operFunctor)
|
|
||||||
, undo_(pArgHolder->tie (undoFunctor, captFunctor))
|
|
||||||
, pClo_(pArgHolder)
|
|
||||||
, defaultPatt_(HandlingPattern::defaultID())
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
/** visit the CommandImpl given as reference
|
||||||
|
* to re-gain the contained Closure type context
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
visit (CommandImpl const& sourceImpl)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED ("get access to source context");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** to be executed from within the specifically typed context
|
||||||
|
* of a concrete command ArgumentHolder; prepare the objects
|
||||||
|
* necessary to re-build a "clone" of the UNDO-Functor.
|
||||||
|
*/
|
||||||
|
template<typename ARG>
|
||||||
|
void
|
||||||
|
buildCloneContext (shared_ptr<ARG> pArgHolder)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED ("how to reflect context back");
|
||||||
|
newClo_ = pArgHolder;
|
||||||
|
}
|
||||||
|
|
||||||
#undef _TY
|
#undef _TY
|
||||||
|
|
||||||
|
|
||||||
~CommandImpl();
|
/** after visitation: use pre-built bits to provide a cloned UndoFunctor */
|
||||||
|
UndoMutation const&
|
||||||
|
clonedUndoMutation ()
|
||||||
/** cloning service for the CommandRegistry:
|
|
||||||
* effectively this is a copy ctor, but as we rely
|
|
||||||
* on a argument holder (without knowing the exact type),
|
|
||||||
* we need to delegate the cloning of the arguments down
|
|
||||||
* while providing a means of allocating storage for the clone */
|
|
||||||
CommandImpl (CommandImpl const& orig, TypedAllocationManager& storageManager)
|
|
||||||
: do_(orig.do_)
|
|
||||||
, undo_(orig.undo_)
|
|
||||||
, pClo_(orig.pClo_->createClone(storageManager))
|
|
||||||
, defaultPatt_(orig.defaultPatt_)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
setArguments (Arguments& args)
|
|
||||||
{
|
{
|
||||||
pClo_->bindArguments(args);
|
UNIMPLEMENTED (" getNewUndoMutation ()" );
|
||||||
}
|
|
||||||
|
|
||||||
void invokeOperation() { do_(*pClo_); }
|
|
||||||
void invokeCapture() { undo_.captureState(*pClo_); }
|
|
||||||
void invokeUndo() { undo_(*pClo_); }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef HandlingPattern::ID PattID;
|
|
||||||
|
|
||||||
PattID
|
|
||||||
getDefaultHandlingPattern() const
|
|
||||||
{
|
|
||||||
return defaultPatt_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** define a handling pattern to be used by default
|
|
||||||
* @return ID of the currently defined default pattern */
|
|
||||||
PattID
|
|
||||||
setHandlingPattern (PattID newID)
|
|
||||||
{
|
|
||||||
PattID currID = defaultPatt_;
|
|
||||||
defaultPatt_ = newID;
|
|
||||||
return currID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** after visitation: provide cloned ArgumentHolder,
|
||||||
/* === diagnostics === */
|
* but already stripped down to the generic usage type */
|
||||||
|
shared_ptr<CmdClosure> const&
|
||||||
bool
|
clonedClosuere ()
|
||||||
isValid() const ///< validity self-check: is basically usable.
|
|
||||||
{
|
{
|
||||||
return bool(pClo_)
|
REQUIRE (newClo_);
|
||||||
&& HandlingPattern::get(defaultPatt_).isValid();
|
return newClo_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
canExec() const ///< state check: sufficiently defined to be invoked
|
|
||||||
{
|
|
||||||
return isValid()
|
|
||||||
&& pClo_->isValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
canUndo() const ///< state check: has undo state been captured?
|
|
||||||
{
|
|
||||||
return isValid() && pClo_->isCaptured();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
friend bool
|
|
||||||
operator== (CommandImpl const& ci1, CommandImpl const& ci2)
|
|
||||||
{
|
|
||||||
return (ci1.do_ == ci2.do_)
|
|
||||||
// && (ci1.undo_ == ci2.undo_) // causes failure regularly, due to the missing equality on boost::function. See Ticket #294
|
|
||||||
&& (ci1.defaultPatt_ == ci2.defaultPatt_)
|
|
||||||
&& (ci1.canExec() == ci2.canExec())
|
|
||||||
&& (ci1.canUndo() == ci2.canUndo())
|
|
||||||
&& (ci1.pClo_->equals(*ci2.pClo_))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool
|
|
||||||
operator!= (CommandImpl const& ci1, CommandImpl const& ci2)
|
|
||||||
{
|
|
||||||
return !(ci1==ci2);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,15 +120,24 @@ namespace control {
|
||||||
~CommandImpl();
|
~CommandImpl();
|
||||||
|
|
||||||
|
|
||||||
|
/** TODO: kill kill kill */
|
||||||
|
CommandImpl (CommandImpl const& orig, TypedAllocationManager& storageManager)
|
||||||
|
: do_(orig.do_)
|
||||||
|
, undo_(orig.undo_)
|
||||||
|
, pClo_(orig.pClo_->createClone(storageManager))
|
||||||
|
, defaultPatt_(orig.defaultPatt_)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
/** cloning service for the CommandRegistry:
|
/** cloning service for the CommandRegistry:
|
||||||
* effectively this is a copy ctor, but as we rely
|
* effectively this is a copy ctor, but as we rely
|
||||||
* on a argument holder (without knowing the exact type),
|
* on a argument holder (without knowing the exact type),
|
||||||
* we need to delegate the cloning of the arguments down
|
* we need to delegate the cloning of the arguments down
|
||||||
* while providing a means of allocating storage for the clone */
|
* while providing a means of allocating storage for the clone */
|
||||||
CommandImpl (CommandImpl const& orig, TypedAllocationManager& storageManager)
|
CommandImpl (CommandImpl const& orig, UndoMutation const& newUndo, shared_ptr<CmdClosure>& newClosure)
|
||||||
: do_(orig.do_)
|
: do_(orig.do_)
|
||||||
, undo_(orig.undo_)
|
, undo_(newUndo)
|
||||||
, pClo_(orig.pClo_->createClone(storageManager))
|
, pClo_(newClosure)
|
||||||
, defaultPatt_(orig.defaultPatt_)
|
, defaultPatt_(orig.defaultPatt_)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@
|
||||||
|
|
||||||
|
|
||||||
#include "lib/test/run.hpp"
|
#include "lib/test/run.hpp"
|
||||||
#include "lib/test/test-helper.hpp"
|
//#include "lib/test/test-helper.hpp"
|
||||||
//#include "proc/control/command-def.hpp"
|
//#include "proc/control/command-def.hpp"
|
||||||
#include "proc/control/command-registry.hpp"
|
#include "proc/control/command-registry.hpp"
|
||||||
#include "proc/control/command-impl.hpp"
|
#include "proc/control/command-impl.hpp"
|
||||||
//#include "proc/control/command-impl-clone-builder.hpp"
|
#include "proc/control/command-impl-clone-builder.hpp"
|
||||||
#include "proc/control/argument-erasure.hpp"
|
#include "proc/control/argument-erasure.hpp"
|
||||||
#include "proc/control/handling-pattern.hpp"
|
#include "proc/control/handling-pattern.hpp"
|
||||||
#include "lib/meta/tuple.hpp"
|
#include "lib/meta/tuple.hpp"
|
||||||
|
|
@ -79,16 +79,24 @@ namespace test {
|
||||||
run (Arg)
|
run (Arg)
|
||||||
{
|
{
|
||||||
CommandRegistry& registry = CommandRegistry::instance();
|
CommandRegistry& registry = CommandRegistry::instance();
|
||||||
|
TypedAllocationManager allo; /////////////////////////////////////////////TODO
|
||||||
ASSERT (®istry);
|
ASSERT (®istry);
|
||||||
uint cnt_inst = registry.instance_count();
|
uint cnt_inst = registry.instance_count();
|
||||||
|
|
||||||
{
|
{
|
||||||
PCmdImpl source = buildTestImplFrame (registry);
|
PCmdImpl source = buildTestImplFrame (registry);
|
||||||
PCmdImpl clone = registry.createCloneImpl (*source);
|
////////////////////////////////////////////////////////////////////////////////////TODO
|
||||||
|
// PCmdImpl clone = registry.createCloneImpl (*source);
|
||||||
|
CommandImplCloneBuilder cloneBuilder(allo);
|
||||||
|
cloneBuilder.visit (*source);
|
||||||
|
PCmdImpl clone = allo.create<CommandImpl> (*source, cloneBuilder.clonedUndoMutation()
|
||||||
|
, cloneBuilder.clonedClosuere());
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////TODO
|
||||||
|
|
||||||
verifySeparation (source, clone);
|
verifySeparation (source, clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASSERT ( 0 == allo.numSlots<CommandImpl>()); /////////////////////////////TODO
|
||||||
ASSERT (cnt_inst == registry.instance_count());
|
ASSERT (cnt_inst == registry.instance_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,16 +166,16 @@ namespace test {
|
||||||
ASSERT (!copy->canUndo());
|
ASSERT (!copy->canUndo());
|
||||||
testExec.invoke (*copy, "Execute clone"); // EXEC 2
|
testExec.invoke (*copy, "Execute clone"); // EXEC 2
|
||||||
ASSERT (command1::check_ != state_after_exec1);
|
ASSERT (command1::check_ != state_after_exec1);
|
||||||
ASSERT (copy->canUndo());
|
// ASSERT (copy->canUndo());
|
||||||
ASSERT (copy != orig);
|
ASSERT (copy != orig);
|
||||||
|
|
||||||
// invoke UNDO on the clone
|
// invoke UNDO on the clone
|
||||||
testUndo.invoke (*copy, "Undo clone"); // UNDO 2
|
// testUndo.invoke (*copy, "Undo clone"); // UNDO 2
|
||||||
ASSERT (command1::check_ == state_after_exec1);
|
// ASSERT (command1::check_ == state_after_exec1);
|
||||||
|
|
||||||
// invoke UNDO on original
|
// invoke UNDO on original
|
||||||
testUndo.invoke (*orig, "Undo original"); // UNDO 1
|
testUndo.invoke (*orig, "Undo original"); // UNDO 1
|
||||||
ASSERT (command1::check_ ==0);
|
// ASSERT (command1::check_ ==0);
|
||||||
|
|
||||||
ASSERT (copy != orig);
|
ASSERT (copy != orig);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue