diff --git a/src/include/logging.h b/src/include/logging.h index b48f3bdff..ad67cb300 100644 --- a/src/include/logging.h +++ b/src/include/logging.h @@ -85,6 +85,7 @@ NOBUG_CPP_DEFINE_FLAG_PARENT ( mmapings_dbg, backend_dbg); NOBUG_CPP_DEFINE_FLAG_PARENT ( threads_dbg, backend_dbg); /** base of debug logging for the proc layer */ NOBUG_CPP_DEFINE_FLAG_PARENT ( proc_dbg, debugging); +NOBUG_CPP_DEFINE_FLAG_PARENT ( command_dbg, proc_dbg); /** base of debug logging for the gui */ NOBUG_CPP_DEFINE_FLAG_PARENT ( gui_dbg, debugging); /** base if debug logging for the support library */ diff --git a/src/proc/control/command-argument-holder.hpp b/src/proc/control/command-argument-holder.hpp index 1e627c9ca..10daadaf9 100644 --- a/src/proc/control/command-argument-holder.hpp +++ b/src/proc/control/command-argument-holder.hpp @@ -192,6 +192,7 @@ namespace control { } + typedef typename CommandSignature::OperateSig SIG_op; typedef typename CommandSignature::CaptureSig SIG_cap; typedef typename CommandSignature::UndoOp_Sig SIG_undo; diff --git a/src/proc/control/command-def.hpp b/src/proc/control/command-def.hpp index ad8a17152..5dac4c4d2 100644 --- a/src/proc/control/command-def.hpp +++ b/src/proc/control/command-def.hpp @@ -51,6 +51,7 @@ #include "lib/error.hpp" #include "include/symbol.hpp" #include "proc/control/command.hpp" +#include "proc/control/command-impl.hpp" /////TODO: any chance to get rid of this import here?? #include "proc/control/command-registry.hpp" #include "proc/control/command-signature.hpp" #include "proc/control/command-mutation.hpp" @@ -128,9 +129,9 @@ namespace control { REQUIRE (captFunctor_); CommandRegistry& registry = CommandRegistry::instance(); - CommandImpl& completedDef = registry.newCommandImpl(operFunctor_ - ,undoFunctor_ - ,captFunctor_); + CommandImpl* completedDef = registry.newCommandImpl(operFunctor_ + ,captFunctor_ + ,undoFunctor_); prototype_.activate(completedDef); ENSURE (prototype_); return *this; diff --git a/src/proc/control/command-impl.cpp b/src/proc/control/command-impl.cpp index a2aed63c3..a0ab3e174 100644 --- a/src/proc/control/command-impl.cpp +++ b/src/proc/control/command-impl.cpp @@ -47,14 +47,6 @@ namespace control { /** */ - template - void - CommandImpl::bindArg (Tuple const&) - { - UNIMPLEMENTED ("actually bind arguments, maybe create ArgumentHolder"); - } - - void CommandImpl::exec (HandlingPattern const& execPattern) { diff --git a/src/proc/control/command-impl.hpp b/src/proc/control/command-impl.hpp index e329d6bfb..7778d0ce7 100644 --- a/src/proc/control/command-impl.hpp +++ b/src/proc/control/command-impl.hpp @@ -44,17 +44,20 @@ #include "proc/control/command.hpp" #include "proc/control/command-mutation.hpp" +#include "proc/control/command-argument-holder.hpp" #include "lib/bool-checkable.hpp" #include #include -//#include - +#include +#include namespace control { + using std::tr1::function; + using std::tr1::shared_ptr; @@ -69,8 +72,40 @@ namespace control { Mutation do_; UndoMutation undo_; + shared_ptr pClo_; + + + template + 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 Func_op; + typedef function Func_cap; + typedef function Func_undo; + }; +#define _TY(_ID_) typename _Type::_ID_ + public: - /* === command registry === */ + /** build a new implementation frame, and do the initial wiring. + * On the interface the specific type is discarded afterwards. + * This information is still kept though, as encoded into the vtable + * of the embedded FunErasure objects holding the command operation + * and undo functors, and the vtable of the embedded CmdClosure */ + template + CommandImpl (shared_ptr 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) + { } + +#undef _TY ~CommandImpl(); @@ -84,7 +119,11 @@ namespace control { template - void bindArg (Tuple const&); + void bindArg (Tuple const&) + { + UNIMPLEMENTED ("actually bind arguments, maybe create ArgumentHolder"); + } + /* === diagnostics === */ diff --git a/src/proc/control/command-registry.hpp b/src/proc/control/command-registry.hpp index b82a27986..4792392da 100644 --- a/src/proc/control/command-registry.hpp +++ b/src/proc/control/command-registry.hpp @@ -41,20 +41,26 @@ #include "lib/error.hpp" #include "lib/singleton.hpp" #include "lib/sync.hpp" +#include "lib/format.hpp" +#include "include/logging.h" //#include "lib/bool-checkable.hpp" #include "proc/control/command.hpp" +#include "proc/control/command-signature.hpp" +#include "proc/control/command-argument-holder.hpp" //#include "proc/control/memento-tie.hpp" +#include //#include -//#include +#include namespace control { + using std::tr1::shared_ptr; // using std::ostream; -// using std::string; + using std::string; @@ -121,41 +127,90 @@ namespace control { } - /** set up a new command implementation frame */ + /** set up a new command implementation frame + * @return pointer to a newly created CommandImpl, allocated + * through the registry. The caller is responsible for + * deallocating this frame by calling #killCommandImpl + */ template< typename SIG_OPER ///< signature of the command operation - , typename SIG_UNDO ///< signature to undo the command , typename SIG_CAPT ///< signature for capturing undo state + , typename SIG_UNDO ///< signature to undo the command > - CommandImpl& - newCommandImpl (function& operFunctor_ - ,function& undoFunctor_ - ,function& captFunctor_) + CommandImpl* + newCommandImpl (function& operFunctor + ,function& captFunctor + ,function& undoFunctor) { Lock sync(this); - UNIMPLEMENTED ("set up a new impl instance located within the instance table"); - } + + // derive the storage type necessary + // to hold the command arguments and UNDO memento + typedef typename UndoSignature::Memento Mem; + typedef ArgumentHolder Arguments; + + shared_ptr pArg ( new (allocateSlot()) Arguments() + , &kill + ); + void* implStorage = 0; + try + { + implStorage = allocateSlot(); + ASSERT (implStorage); + + return new(implStorage) CommandImpl (pArg, operFunctor,captFunctor,undoFunctor); + } + catch(...) + { + if (implStorage) + releaseSlot (implStorage); + throw; + } } - /** discard an command implementation frame */ + /** delete the command implementation and free the corresponding allocation */ + static void killCommandImpl (CommandImpl* entry) { kill(entry); } + + + template static void - killCommandImpl (CommandImpl* entry) + kill (IMP* entry) { ///////////////////////////////////////////////TODO: clean behaviour while in App shutdown (Ticket #196) - instance().removeImpl(entry); + instance().destroyImpl(entry); } private: - CommandImpl* - createImpl () + template + void* + allocateSlot () { - ///////////////////////////////TODO: still necessary? + TODO ("redirect to the corresponding pool allocator"); } + template void - removeImpl (CommandImpl* entry) + releaseSlot (void* entry) { - UNIMPLEMENTED ("remove entry from instance table"); + TODO ("redirect to the corresponding pool allocator"); + } + + + template + void + destroyImpl (IMP* entry) + { + if (!entry) return; + try + { + entry->~IMP(); + } + catch(...) + { + WARN (command_dbg, "dtor of %s failed: %s", util::tyStr(entry).c_str() + , lumiera_error() ); + } + releaseSlot (entry); } }; diff --git a/src/proc/control/command.cpp b/src/proc/control/command.cpp index 690c51b03..fad9cd19d 100644 --- a/src/proc/control/command.cpp +++ b/src/proc/control/command.cpp @@ -118,14 +118,15 @@ namespace control { * @throw std::bad_alloc, in which case * CommandRegistry::killCommandImpl is invoked */ Command& - Command::activate (CommandImpl& implFrame) + Command::activate (CommandImpl* implFrame) { static format fmt("Command \"%s\" already defined"); + REQUIRE (implFrame); if (this->isValid()) throw error::Logic (str (fmt % *this), LUMIERA_ERROR_DUPLICATE_COMMAND); - _Handle::activate (&implFrame, CommandRegistry::killCommandImpl); + _Handle::activate (implFrame, CommandRegistry::killCommandImpl); INFO (command, "Command \"%s\" defined OK", cStr(*this)); return *this; diff --git a/src/proc/control/command.hpp b/src/proc/control/command.hpp index 0cd713e1f..51b7c57a9 100644 --- a/src/proc/control/command.hpp +++ b/src/proc/control/command.hpp @@ -115,7 +115,7 @@ namespace control { /* === command lifecycle === */ - Command& activate (CommandImpl&); + Command& activate (CommandImpl*); template Command& bindArg (Tuple const&);