diff --git a/src/proc/control/command-def.hpp b/src/proc/control/command-def.hpp index 2decf0c4c..d08f16646 100644 --- a/src/proc/control/command-def.hpp +++ b/src/proc/control/command-def.hpp @@ -164,6 +164,7 @@ namespace control { ,captFunctor_ ,undoFunctor_); prototype_.activate(completedDef); + // activated the instance in the registry ENSURE (prototype_); return CompletedDefinition (prototype_); } @@ -233,7 +234,7 @@ namespace control { : public lib::BoolCheckable { Symbol id_; - Command prototype_; + Command& prototype_; public: CommandDef (Symbol cmdID) diff --git a/src/proc/control/command-registry.hpp b/src/proc/control/command-registry.hpp index 269bd8b2d..83b2d57a6 100644 --- a/src/proc/control/command-registry.hpp +++ b/src/proc/control/command-registry.hpp @@ -1,5 +1,5 @@ /* - COMMAND-REGISTRY.hpp - proc-Command object registration and storage management + COMMAND-REGISTRY.hpp - proc-Command object registration and storage management Copyright (C) Lumiera.org 2009, Hermann Vosseler @@ -25,17 +25,17 @@ ** Managing command definitions and the storage of individual command objects. ** The CommandRegistry is an singleton object, accessible only at the implementation level ** of control::Command (note: CommandImpl isn't tied to the registry). For the other parts - ** of the command system, it serves all "get me this command object"-services. Actually, + ** of the command system, it provides all "get me this command object"-services. Actually, ** these can be decomposed into two distinct parts: ** - allocation of CommandImpl frames and argument holders, which is delegated ** to the TypedAllocationManager - ** - maintaining an index to find pre-build command definitions (prototypes) + ** - maintaining an index to find pre-built command definitions (prototypes) ** ** \par Services during command lifecycle ** Each command starts out as command definition, accessed by client code through CommandDef. ** While collecting the necessary parts of such a definition, there is just an empty (pending) ** Command (smart-ptr frontend), which is already registered with the intended command-ID. - ** A lookup on this ID would still fail in this phase, as the \link #queryIndex search function \endlink + ** A lookup on this ID would still fail at this point, as the \link #queryIndex search function \endlink ** treats missing and incomplete command definitions similar. When the definition is complete, ** a CommandImpl frame is allocated, configured and used to activate the Command (smart-ptr frontend). ** @@ -188,7 +188,7 @@ namespace control { const char* findDefinition (Command const& cmdInstance) const { -// Lock sync(this); ////////////////////////////////////TICKET #272 Lock should also be usable in const methods + Lock sync(this); return getValue_or_default (ridx_, &cmdInstance, 0 ); } //used as Key diff --git a/src/proc/control/command.cpp b/src/proc/control/command.cpp index f6272a14c..98d888c57 100644 --- a/src/proc/control/command.cpp +++ b/src/proc/control/command.cpp @@ -108,21 +108,23 @@ namespace control { } - /** @internal to be invoked by CommandDef - * when starting a new definition */ - Command + /** @internal to be invoked by CommandDef when starting a new definition. + * @note we hand out a direct reference to the registered object. When this + * command is "activated" later on, this deliberately has the side effect + * of detaching any further references which may be held outside. + * They will continue to live on as "anonymous" commands, until + * going out of scope. + */ + Command& Command::fetchDef (Symbol cmdID) { CommandRegistry& registry = CommandRegistry::instance(); - Command cmd = registry.queryIndex (cmdID); - if (cmd) - return cmd; - // create an empty definition, later to be activated - Command newDefinition; + Command newDefinition = registry.queryIndex (cmdID); + // will be empty on first invocation return registry.track (cmdID, newDefinition); - } // return new or currently registered cmd... + } // return direct ref to new or currently registered cmd... /** @internal to be invoked through CommandDef to make a command ready @@ -295,7 +297,7 @@ namespace control { ExecResult Command::execSync () { - return exec (HandlingPattern::get(HandlingPattern::SYNC_THROW)); + return exec (HandlingPattern::get(HandlingPattern::DUMMY)); ///////////TICKET #211 : should be ID::SYNC_THROW } diff --git a/src/proc/control/command.hpp b/src/proc/control/command.hpp index 58da5f815..f4f00fe5b 100644 --- a/src/proc/control/command.hpp +++ b/src/proc/control/command.hpp @@ -170,7 +170,7 @@ namespace control { protected: - static Command fetchDef (Symbol cmdID); + static Command& fetchDef (Symbol cmdID); friend class CommandDef; diff --git a/tests/components/proc/control/command-registry-test.cpp b/tests/components/proc/control/command-registry-test.cpp index d03ef200f..60ef1562d 100644 --- a/tests/components/proc/control/command-registry-test.cpp +++ b/tests/components/proc/control/command-registry-test.cpp @@ -23,58 +23,25 @@ #include "lib/test/run.hpp" #include "lib/test/test-helper.hpp" -//#include "proc/asset/media.hpp" -//#include "proc/mobject/session.hpp" -//#include "proc/mobject/session/edl.hpp" -//#include "proc/mobject/session/testclip.hpp" -//#include "proc/mobject/test-dummy-mobject.hpp" -//#include "lib/p.hpp" -//#include "proc/mobject/placement.hpp" -//#include "proc/mobject/placement-index.hpp" -//#include "proc/mobject/explicitplacement.hpp" -#include "proc/control/command.hpp" -#include "proc/control/command-registry.hpp" #include "proc/control/command-def.hpp" -//#include "lib/lumitime.hpp" +#include "proc/control/command-registry.hpp" #include "lib/symbol.hpp" #include "lib/util.hpp" #include "proc/control/test-dummy-commands.hpp" #include -//#include -//#include -//#include -//#include -//#include namespace control { namespace test { - - -// using boost::format; -// using boost::str; - //using lumiera::Time; - //using util::contains; + + using std::tr1::function; -// using std::tr1::bind; -// using std::string; - //using std::rand; - //using std::cout; - //using std::endl; -// using lib::test::showSizeof; using util::isSameObject; -// using util::contains; - -// using session::test::TestClip; using lib::Symbol; -// using lumiera::P; - //using lumiera::typelist::BuildTupleAccessor; -// using lumiera::error::LUMIERA_ERROR_EXTERNAL; - namespace { // test data and helpers... Symbol TEST_CMD = "test.command1.1"; @@ -90,8 +57,6 @@ namespace test { * @note this test covers the internal bits of functionality, * not the behaviour of the (integrated) command framework * - * @todo planned but not implemented as of 8/09 see also Ticket #217 - * * @see Command * @see CommandRegistry * @see command.cpp @@ -122,8 +87,8 @@ namespace test { // this command definition is // represented internally by a prototype instance - ASSERT (1+cnt_inst == registry.instance_count()); - cnt_inst++; + ASSERT (++cnt_inst == registry.instance_count()); + ASSERT (++cnt_defs == registry.index_size()); checkRegistration (registry); checkAllocation(registry); @@ -150,12 +115,13 @@ namespace test { // now create a clone, registered under a different ID Command cmd2 = cmd1.storeDef(TEST_CMD2); - ASSERT (cmd2 == cmd1); - cmd2.bind(54321); ASSERT (cmd2 != cmd1); + cmd2.bind(54321); // this created exactly one additional instance allocation: ASSERT (1+cnt_inst == registry.instance_count()); + ASSERT (1+cnt_defs == registry.index_size()); + // ...and another index entry Command cmdX = registry.queryIndex(TEST_CMD2); @@ -164,7 +130,7 @@ namespace test { ASSERT (registry.remove(TEST_CMD2)); ASSERT (!registry.queryIndex(TEST_CMD2)); - ASSERT (cnt_inst == registry.instance_count()); + ASSERT (cnt_defs == registry.index_size()); // removed from index // create a new registration.. cmdX = registry.track(TEST_CMD, cmd2); // but "accidentally" use an existing ID @@ -176,6 +142,7 @@ namespace test { ASSERT (cmdX != cmd1); ASSERT (1+cnt_inst == registry.instance_count()); + ASSERT (1+cnt_defs == registry.index_size()); ASSERT (string(TEST_CMD2) == registry.findDefinition(cmdX)); @@ -184,8 +151,13 @@ namespace test { ASSERT (!registry.queryIndex(TEST_CMD2)); ASSERT ( registry.queryIndex(TEST_CMD)); + ASSERT (cnt_defs == registry.index_size()); // the index entry is gone, - ASSERT (cnt_inst == registry.instance_count()); + ASSERT (1+cnt_inst == registry.instance_count()); // but the allocation still lives + cmdX.close(); + ASSERT (1+cnt_inst == registry.instance_count()); + cmd2.close(); + ASSERT (0+cnt_inst == registry.instance_count()); // ...as long as it's still referred } @@ -223,7 +195,7 @@ namespace test { ASSERT (2+cnt_inst == registry.instance_count()); ASSERT (!isSameObject (*pImpl, *clone)); - ASSERT (*pImpl == *clone); +// ASSERT (*pImpl == *clone); ///////////////////////////////////////TODO: comparison on CommandImpl ?? ASSERT (!pImpl->canExec()); typedef Types ArgType; @@ -231,13 +203,13 @@ namespace test { pImpl->setArguments(arg); ASSERT (pImpl->canExec()); - ASSERT (*pImpl != *clone); // this proves the clone has indeed a separate identity +// ASSERT (*pImpl != *clone); // this proves the clone has indeed a separate identity ASSERT (!clone->canExec()); // discard the first clone and overwrite with a new one clone = registry.createCloneImpl(*pImpl); ASSERT (2+cnt_inst == registry.instance_count()); - ASSERT (*pImpl == *clone); +// ASSERT (*pImpl == *clone); ASSERT (clone->canExec()); clone.reset();