/* COMMAND-CLOSURE.hpp - defining execution targets and parameters for commands Copyright (C) Lumiera.org 2009, Hermann Vosseler This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file command-closure.hpp ** A closure enabling self-contained execution of commands within the ProcDispatcher. ** After defining a proc-layer command, at some point the function arguments ** of the contained operation are "closed" by storing concrete argument values. ** These values will be fed later on to the operation when the command is invoked. ** ** Most of the command machinery accesses this function closure through the generic ** interface CmdClosure, while, when defining a command, subclasses typed to the specific ** function arguments are created. Especially, there is an StorageHolder template, ** which is used to define the storage for the concrete arguments. This StorageHolder ** internally contains an OpClosure instance (where SIG is the signature of the ** actual command operation function), which implements the invocation of the ** operation function with the stored argument tuple. ** ** \par Command Closure and Lifecycle ** When defining a command, Mutation objects are to be created based on a concrete function. ** These are stored embedded into a type erasure container, thus disposing the specific type ** information of the function and function arguments. Each command needs an Mutation object ** holding the command operation and an UndoMutation holding the undo functor. ** ** Later on, any command needs to be made ready for execution by binding it to a specific ** execution environment, which especially includes the target objects to be mutated by the ** command. Effectively, this means "closing" the Mutation (and UNDO) functor(s)) with the ** actual function arguments. These arguments are stored embedded within an StorageHolder, ** which thereby acts as closure. Besides, the StorageHolder also has to accommodate for ** storage holding the captured UNDO state (memento). Internally the StorageHolder ** has to keep track of the actual types, thus allowing to re-construct the concrete ** function signature when closing the Mutation. ** ** Finally, when invoking the command, it passes a \c CmdClosure& to the Mutation object, ** which allows the embedded function to be called with the concrete arguments. Besides ** just invoking it, a command can also be used like a prototype object. To support this ** use case it is possible to re-bind to a new set of command arguments, and to create ** a clone copy of the argument (holder) without disclosing the actual types involved. ** ** @see Command ** @see ProcDispatcher ** @see command-storage-holder.hpp ** @see command-op-closure.hpp ** */ #ifndef CONTROL_COMMAND_CLOSURE_H #define CONTROL_COMMAND_CLOSURE_H #include "lib/bool-checkable.hpp" #include "lib/meta/function-erasure.hpp" #include "proc/control/argument-erasure.hpp" #include "lib/diff/gen-node.hpp" #include #include namespace proc { namespace control { using lib::meta::FunErasure; using lib::meta::StoreFunction; using std::string; LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS); ///< Command functor not yet usable, because arguments aren't bound /** * A neutral container internally holding * the functor used to implement the Command */ typedef FunErasure CmdFunctor; class CommandImplCloneBuilder; class CmdClosure; typedef std::shared_ptr PClo; /** Interface */ class CmdClosure : public lib::BoolCheckable { public: virtual ~CmdClosure() {} virtual operator string() const =0; virtual bool isValid () const =0; ///< does this closure hold a valid argument tuple? virtual bool isCaptured () const =0; ///< does this closure hold captured UNDO state? virtual bool equals (CmdClosure const&) const =0; ///< is equivalent to the given other closure? virtual void bindArguments (Arguments&) =0; ///< store a set of parameter values within this closure virtual void bindArguments (lib::diff::Rec const&) =0; ///< store a set of parameter values, passed as GenNode sequence virtual void invoke (CmdFunctor const&) =0; ///< invoke functor using the stored parameter values virtual void accept (CommandImplCloneBuilder&) const =0; ///< assist with creating clone closure without disclosing concrete type }; class AbstractClosure : public CmdClosure { bool isValid() const override { return false; } bool isCaptured() const override { return false; } void accept (CommandImplCloneBuilder&) const override {} }; }} // namespace proc::control #endif /*CONTROL_COMMAND_CLOSURE_H*/