LUMIERA.clone/src/proc/control/command-mutation.hpp

161 lines
4.5 KiB
C++
Raw Normal View History

2009-06-08 04:46:07 +02:00
/*
2009-06-19 14:47:37 +02:00
COMMAND-MUTATION.hpp - functor encapsulating the actual operation of proc-Command
2010-12-17 23:28:49 +01:00
2009-06-08 04:46:07 +02:00
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
2010-12-17 23:28:49 +01:00
2009-06-08 04:46:07 +02:00
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
2010-12-17 23:28:49 +01:00
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
2009-06-08 04:46:07 +02:00
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.
2010-12-17 23:28:49 +01:00
2009-06-08 04:46:07 +02:00
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.
2010-12-17 23:28:49 +01:00
2009-06-08 04:46:07 +02:00
*/
2009-06-19 14:47:37 +02:00
/** @file command-mutation.hpp
** Core of a Proc-Layer command: functor containing the operation to be executed.
** Each command holds two of these functors: one representing the actual operation
** and one to undo the effect of this operation. The latter involves the capturing
** and storing of a "memento" value behind the scenes. But towards Command, the
** Mutation acts as interface to conceal these details, as well as the actual
** type and parameters of the functions to be invoked. Thus, Mutation's
** public interface just consists of a function call operator.
**
** Mutation objects are based on lib::OpaqueHolder, which yields a fixed size storage,
** allowing them e.g. to be embedded immediately within the CommandImpl frame.
**
**
2009-06-08 04:46:07 +02:00
** @see Command
** @see ProcDispatcher
** @see MementoTie binding memento state
2009-06-08 04:46:07 +02:00
**
*/
#ifndef CONTROL_COMMAND_MUTATION_H
#define CONTROL_COMMAND_MUTATION_H
2009-06-08 04:46:07 +02:00
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include "proc/control/command-closure.hpp"
#include "proc/control/memento-tie.hpp"
2009-06-08 04:46:07 +02:00
#include <iostream>
#include <string>
2009-06-08 04:46:07 +02:00
namespace proc {
2009-06-08 04:46:07 +02:00
namespace control {
using std::ostream;
using std::string;
2009-06-08 04:46:07 +02:00
2009-06-08 04:46:07 +02:00
/**
* Unspecific command functor for implementing Proc-Layer Command.
* To be created from an tr1::function object, which later on gets
* any necessary arguments from a closure passed in on invocation.
* The concrete type of the function and the arguments is
* concealed (erased) on the interface.
2009-06-08 04:46:07 +02:00
*/
class Mutation
{
const CmdFunctor func_;
2009-06-08 04:46:07 +02:00
public:
template<typename SIG>
Mutation (function<SIG> const& func)
: func_(func)
{ }
2009-06-08 04:46:07 +02:00
void
operator() (CmdClosure& clo)
{
if (!clo)
throw lumiera::error::State ("Lifecycle error: function arguments not ready",
LUMIERA_ERROR_UNBOUND_ARGUMENTS);
clo.invoke (func_);
}
/// Supporting equality comparisons...
friend bool
operator== (Mutation const& m1, Mutation const& m2)
{
return (m1.func_ == m2.func_);
}
friend bool
operator!= (Mutation const& m1, Mutation const& m2)
{
return !(m1==m2);
}
2009-06-08 04:46:07 +02:00
};
2009-06-08 04:46:07 +02:00
/**
* Specialised version of the command Mutation functor,
* used to implement the UNDO functionality. The operation
* executed when invoking this functor is the UNDO operation
* of the respective command; additionally we need another
* functor to capture the state to be restored on UNDO.
* Both functors are wired up internally to cooperate
* and store the state (memento), which is implemented
* by the specifically typed MementoTie object passed
* in on construction. All these specific details
* are concealed (erased) on the interface
2009-06-08 04:46:07 +02:00
*/
class UndoMutation
: public Mutation
{
Mutation captureMemento_;
2009-06-08 04:46:07 +02:00
public:
template<typename SIG, typename MEM>
UndoMutation (MementoTie<SIG,MEM> & mementoHolder)
: Mutation (mementoHolder.tieUndoFunc())
, captureMemento_(mementoHolder.tieCaptureFunc())
{ }
Mutation&
captureState (CmdClosure& clo)
{
if (!clo)
throw lumiera::error::State ("need additional function arguments to be able to capture UNDO state",
LUMIERA_ERROR_UNBOUND_ARGUMENTS);
captureMemento_(clo);
return *this;
}
2009-06-08 04:46:07 +02:00
};
}} // namespace proc::control
2009-06-08 04:46:07 +02:00
#endif