LUMIERA.clone/src/proc/control/command-closure.hpp
Ichthyostega bb7bba5dc2 Commands: add API to unbind and discard command arguments
this seems like an obvious functionality and basically harmless,
since commands are designed to be inherently stateful, which is reflected
in all the internal storage holders to expos an assignment operator
(even while the actual implementation is based on placement new instead
of assigning values into the storage, and thus even supports immutable
values). The only possible ramification is that argument values must
be default constructible
2017-04-16 19:21:29 +02:00

129 lines
5.4 KiB
C++

/*
COMMAND-CLOSURE.hpp - defining execution targets and parameters for commands
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
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<SIG> 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.
**
** ## 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 `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/meta/function-erasure.hpp"
#include "proc/control/argument-erasure.hpp"
#include "lib/diff/gen-node.hpp"
#include <memory>
#include <string>
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<StoreFunction> CmdFunctor;
class CommandImplCloneBuilder;
/** Interface */
class CmdClosure
{
public:
virtual ~CmdClosure() {}
explicit operator bool() const { return isValid(); }
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 unbindArguments() =0; ///< discard any parameters and return to _unbound state_
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
};
using PClo = std::shared_ptr<CmdClosure>;
}} // namespace proc::control
#endif /*CONTROL_COMMAND_CLOSURE_H*/