clone builder implemented; problem resolved according to test

This commit is contained in:
Fischlurch 2009-10-10 04:24:27 +02:00
parent e32044e453
commit fdd940feba
4 changed files with 118 additions and 54 deletions

View file

@ -45,6 +45,7 @@
#include "lib/typed-allocation-manager.hpp"
#include "proc/control/command-closure.hpp"
#include "proc/control/memento-tie.hpp"
#include "proc/control/command-impl-clone-builder.hpp"
#include "lib/opaque-holder.hpp"
#include <string>
@ -194,11 +195,12 @@ namespace control {
memento_.template create<MemHolder> (*oAh.memento_);
}
/** create a clone copy, without disclosing the exact type */
PClo
createClone (TypedAllocationManager& storageManager)
/** assist with creating a clone copy;
* this results in invocation of the copy ctor */
void
accept (CommandImplCloneBuilder& visitor) const
{
return storageManager.create<ArgumentHolder> (*this);
visitor.buildCloneContext (*this);
}
@ -230,6 +232,15 @@ namespace control {
return memento_.template create<MemHolder> (undoFunc,captureFunc);
}
/** just re-access an existing memento storage wiring.
* Used when cloning the closure */
MementoTie<SIG,MEM>&
getMementoWiring ()
{
REQUIRE (!empty());
return *memento_;
}
/** direct "backdoor" access to stored memento value.

View file

@ -50,12 +50,13 @@
//#include "proc/control/command-closure.hpp"
#include "proc/control/command-mutation.hpp"
#include "lib/typed-allocation-manager.hpp"
#include "lib/opaque-holder.hpp"
//#include "lib/bool-checkable.hpp"
#include <boost/noncopyable.hpp>
//#include <boost/operators.hpp>
#include <tr1/memory>
//#include <tr1/memory>
//#include <tr1/functional>
@ -63,7 +64,61 @@ namespace control {
using lib::TypedAllocationManager;
// using std::tr1::function;
using std::tr1::shared_ptr;
// using std::tr1::shared_ptr;
using lib::InPlaceBuffer;
namespace impl { // Helper: type erased context for creating command clones
struct CloneContext ///< Interface and empty state
{
virtual ~CloneContext() {}
virtual UndoMutation const& getUndoFunc() { NOTREACHED(); }
virtual PClo const& getClosure() { NOTREACHED(); }
virtual bool isValid() { return false; }
};
class ClonedContext
: public CloneContext
{
PClo newClosure_;
UndoMutation newUndoFunctor_;
virtual UndoMutation const& getUndoFunc() { return newUndoFunctor_; }
virtual PClo const& getClosure() { return newClosure_; }
virtual bool isValid() { return true; }
/** helper for accessing the new cloned closure
* through the specific concrete type. As we need
* to access the closure later, after discarding the
* exact type, we can store only a baseclass pointer.
*/
template<typename ARG>
ARG&
downcast()
{
REQUIRE (INSTANCEOF (ARG, newClosure_.get()));
return static_cast<ARG&> (*newClosure_);
}
public:
template<typename ARG>
ClonedContext ( ARG const& origArgHolder
, TypedAllocationManager& allocator
)
: newClosure_(allocator.create<ARG> (origArgHolder))
, newUndoFunctor_(downcast<ARG>().getMementoWiring())
{ }
};
}//(End) impl namespace
@ -75,76 +130,55 @@ namespace control {
* and the memento storage within the cloned parts.
*/
class CommandImplCloneBuilder
// : public lib::BoolCheckable<CommandImpl
// , boost::noncopyable
// >
: public boost::noncopyable
{
typedef InPlaceBuffer<impl::CloneContext, sizeof(impl::ClonedContext)> ContextHolder;
TypedAllocationManager& allocator_;
shared_ptr<CmdClosure> newClo_;
template<typename ARG>
struct _Type
{
typedef typename ARG::SIG_op SIG_op;
typedef typename ARG::SIG_cap SIG_cap;
typedef typename ARG::SIG_undo SIG_undo;
typedef function<SIG_op> Func_op;
typedef function<SIG_cap> Func_cap;
typedef function<SIG_undo> Func_undo;
};
#define _TY(_ID_) typename _Type<ARG>::_ID_
ContextHolder newContext_;
public:
CommandImplCloneBuilder (TypedAllocationManager allo)
CommandImplCloneBuilder (TypedAllocationManager& allo)
: allocator_(allo)
, newClo_()
{ }
/** 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.
* of a concrete command ArgumentHolder; allocate a clone copy
* and then prepare a new UNDO-Functor, which is correctly wired
* with the memento holder within this new \em clone closure.
* After that point, these prepared parts can be retrieved
* through the public accessor functions; they will be
* used by the command registry to put together a complete
* clone copy of the original CommandImpl.
*/
template<typename ARG>
void
buildCloneContext (shared_ptr<ARG> pArgHolder)
buildCloneContext (ARG const& origArgHolder)
{
UNIMPLEMENTED ("how to reflect context back");
newClo_ = pArgHolder;
REQUIRE (!newContext_->isValid(), "Lifecycle-Error");
newContext_.create<impl::ClonedContext> (origArgHolder, allocator_);
}
#undef _TY
/** after visitation: use pre-built bits to provide a cloned UndoFunctor */
UndoMutation const&
clonedUndoMutation ()
{
UNIMPLEMENTED (" getNewUndoMutation ()" );
REQUIRE (newContext_->isValid());
return newContext_->getUndoFunc();
}
/** after visitation: provide cloned ArgumentHolder,
* but already stripped down to the generic usage type */
shared_ptr<CmdClosure> const&
PClo const&
clonedClosuere ()
{
REQUIRE (newClo_);
return newClo_;
REQUIRE (newContext_->isValid());
return newContext_->getClosure();
}
};

View file

@ -124,7 +124,7 @@ namespace control {
CommandImpl (CommandImpl const& orig, TypedAllocationManager& storageManager)
: do_(orig.do_)
, undo_(orig.undo_)
, pClo_(orig.pClo_->createClone(storageManager))
// , pClo_(orig.pClo_->createClone(storageManager))
, defaultPatt_(orig.defaultPatt_)
{ }
@ -134,7 +134,9 @@ namespace control {
* 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, UndoMutation const& newUndo, shared_ptr<CmdClosure>& newClosure)
CommandImpl (CommandImpl const& orig
,UndoMutation const& newUndo
,shared_ptr<CmdClosure> const& newClosure)
: do_(orig.do_)
, undo_(newUndo)
, pClo_(newClosure)
@ -142,6 +144,23 @@ namespace control {
{ }
/** assist with building a clone copy of this CommandImpl.
* By accepting the clone builder as a visitor and dispatching
* this visitation down into the concrete closure, the builder
* can re-gain the fully typed context available on creation
* of the ComandImpl. Within this context, for the clone
* to be created, the UndoMutation has to be re-wired,
* otherwise it would continue to cooperate with
* original closure.
*/
void
prepareClone (CommandImplCloneBuilder& visitor) const
{
ASSERT (pClo_);
pClo_->accept(visitor);
}
void
setArguments (Arguments& args)
{

View file

@ -88,7 +88,7 @@ namespace test {
////////////////////////////////////////////////////////////////////////////////////TODO
// PCmdImpl clone = registry.createCloneImpl (*source);
CommandImplCloneBuilder cloneBuilder(allo);
cloneBuilder.visit (*source);
source->prepareClone(cloneBuilder);
PCmdImpl clone = allo.create<CommandImpl> (*source, cloneBuilder.clonedUndoMutation()
, cloneBuilder.clonedClosuere());
////////////////////////////////////////////////////////////////////////////////////TODO
@ -166,16 +166,16 @@ namespace test {
ASSERT (!copy->canUndo());
testExec.invoke (*copy, "Execute clone"); // EXEC 2
ASSERT (command1::check_ != state_after_exec1);
// ASSERT (copy->canUndo());
ASSERT (copy->canUndo());
ASSERT (copy != orig);
// invoke UNDO on the clone
// testUndo.invoke (*copy, "Undo clone"); // UNDO 2
// ASSERT (command1::check_ == state_after_exec1);
testUndo.invoke (*copy, "Undo clone"); // UNDO 2
ASSERT (command1::check_ == state_after_exec1);
// invoke UNDO on original
testUndo.invoke (*orig, "Undo original"); // UNDO 1
// ASSERT (command1::check_ ==0);
ASSERT (command1::check_ ==0);
ASSERT (copy != orig);
}