fix further problems uncovered by test; allow for anonymous cloning

This commit is contained in:
Fischlurch 2009-10-09 04:32:22 +02:00
parent 17c7160f02
commit 0bcbf7fee0
5 changed files with 48 additions and 20 deletions

View file

@ -32,8 +32,7 @@
namespace control {
LUMIERA_ERROR_DECLARE (INVALID_ARGUMENTS); ///< Arguments provided for binding doesn't match stored command function parameters
@ -63,7 +62,8 @@ namespace control {
{
TypedArguments<TUP>* dest = dynamic_cast<TypedArguments<TUP>*> (this);
if (!dest)
throw lumiera::error::Invalid("Wrong type or number of arguments");
throw lumiera::error::Invalid("Wrong type or number of arguments"
, LUMIERA_ERROR_INVALID_ARGUMENTS);
return dest->args_;
}

View file

@ -92,13 +92,13 @@ namespace control {
using lumiera::typelist::NullType;
using lumiera::typelist::Tuple;
typedef shared_ptr<CommandImpl> ImplInstance;
typedef function<Command&(ImplInstance const&)> Activation;
namespace stage { ///< helpers for building up a command definition
typedef shared_ptr<CommandImpl> ImplInstance;
typedef function<Command&(ImplInstance const&)> Activation;
template<typename SIG>
@ -245,6 +245,9 @@ namespace control {
Symbol id_;
Command prototype_;
typedef stage::ImplInstance PImpl;
typedef stage::Activation Activation;
public:
CommandDef (Symbol cmdID)
: id_(cmdID)
@ -275,9 +278,9 @@ namespace control {
/** callback from completed command definition stage:
* "arm up" the command handle object and register it
* with the CommandRegistry. */
Command& activate (ImplInstance const& completedDef)
Command& activate (PImpl const& completedDef)
{
prototype_.activate (id_,completedDef);
prototype_.activate (completedDef, id_);
ENSURE (prototype_);
return prototype_;
}

View file

@ -117,10 +117,13 @@ namespace control {
}
/** @internal to be invoked through CommandDef to make a command ready for use
* @throw error::Logic when this is already activated. */
/** @internal make a command ready for use. Typically to be invoked
* through CommandDef during the definition stage, but also used
* for activating clone instances.
* @param cmdID new ID for creating a separate command registration when provided
* @throw error::Logic when \c this is already activated. */
void
Command::activate (Symbol cmdID, shared_ptr<CommandImpl> const& implFrame)
Command::activate (shared_ptr<CommandImpl> const& implFrame, Symbol cmdID)
{
REQUIRE (implFrame);
static format fmt("Command \"%s\" already defined");
@ -129,12 +132,15 @@ namespace control {
duplicate_detected (cmdID);
_Handle::activate (implFrame);
CommandRegistry::instance().track (cmdID, *this);
if (cmdID)
CommandRegistry::instance().track (cmdID, *this);
INFO (command, "Command \"%s\" defined OK", cStr(*this));
}
/** create an independent clone copy of this command
* and register it as new command definition under a different ID */
Command
Command::storeDef (Symbol newCmdID) const
{
@ -144,12 +150,26 @@ namespace control {
duplicate_detected (newCmdID);
Command cloneDefinition;
cloneDefinition.activate (newCmdID, registry.createCloneImpl(impl()));
cloneDefinition.activate (registry.createCloneImpl(this->impl()), newCmdID);
ENSURE (cloneDefinition);
return cloneDefinition;
}
/** create independent clone copy of this command */
Command
Command::newInstance () const
{
CommandRegistry& registry = CommandRegistry::instance();
shared_ptr<CommandImpl> cloneImpl = registry.createCloneImpl(this->impl());
Command clone;
clone.activate (cloneImpl);
ENSURE (clone);
return clone;
}
void
Command::duplicate_detected (Symbol newCmdID) const
{
@ -305,6 +325,10 @@ namespace control {
ExecResult
Command::exec (HandlingPattern const& execPattern)
{
if (!canExec())
throw error::State ("Lifecycle error: command arguments not bound",
LUMIERA_ERROR_UNBOUND_ARGUMENTS);
CommandImpl& thisCommand (_Handle::impl());
return execPattern.invoke (thisCommand, cStr(*this));
}

View file

@ -119,6 +119,7 @@ namespace control {
/** create a clone definition */
Command storeDef (Symbol newCmdID) const;
Command newInstance () const;
Command() { } ///< undefined command
~Command();
@ -175,7 +176,7 @@ namespace control {
protected:
static Command fetchDef (Symbol cmdID);
void activate (Symbol cmdID, shared_ptr<CommandImpl> const&);
void activate (shared_ptr<CommandImpl> const&, Symbol cmdID =0);
friend class CommandDef; //...invoking those two functions during definition stage

View file

@ -155,7 +155,7 @@ namespace test {
def.operation (command1::operate)
.captureUndo (command1::capture);
ASSERT (!def); // undo functor still missing
ASSERT (!Command::get("test.command1.2"));
VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.2") );
def.operation (command1::operate)
.captureUndo (command1::capture)
@ -213,10 +213,10 @@ namespace test {
ASSERT (c1.canExec());
ASSERT (!c1.canUndo());
Command c2 = Command::get("test.command1.3");
ASSERT (c1);
ASSERT (c1.canExec());
ASSERT (!c1.canUndo());
Command c2 = c1.newInstance();
ASSERT (c2);
ASSERT (c2.canExec());
ASSERT (!c2.canUndo());
ASSERT (c1 == c2);
ASSERT (!isSameObject(c1, c2));
@ -226,9 +226,9 @@ namespace test {
c1();
ASSERT (randVal == command1::check_);
ASSERT (c1.canUndo());
ASSERT (c1 != c2);
ASSERT ( c1.canUndo());
ASSERT (!c2.canUndo());
ASSERT (c1 != c2);
c2();
ASSERT (randVal + randVal == command1::check_);