WIP more implementation...

This commit is contained in:
Fischlurch 2009-08-01 17:14:27 +02:00
parent c2d9a02303
commit 8971d667cf
7 changed files with 161 additions and 49 deletions

View file

@ -120,8 +120,8 @@ NOBUG_CPP_DEFINE_FLAG_PARENT ( mmap, backend);
NOBUG_CPP_DEFINE_FLAG_PARENT ( thread, backend); //starting/stopping threads
/** progress log for the proc layer */
NOBUG_CPP_DEFINE_FLAG_PARENT ( proc, progress);
/** progress log for the render subsystem of proc */
NOBUG_CPP_DEFINE_FLAG_PARENT ( render, proc); //ichthyo: did you want this as global channel or as progress child?
/** progress log for proc-layer command dispatch */
NOBUG_CPP_DEFINE_FLAG_PARENT ( command, proc);
/** progress log for the gui */
NOBUG_CPP_DEFINE_FLAG_PARENT ( gui, progress);
/** progress log for the support lib */
@ -130,7 +130,7 @@ NOBUG_CPP_DEFINE_FLAG_PARENT ( resourcecollector, library);
/** progress log for the common lib */
NOBUG_CPP_DEFINE_FLAG_PARENT ( common, progress);
/** progress log, config subsystem */
NOBUG_CPP_DEFINE_FLAG_PARENT ( config, common);
NOBUG_CPP_DEFINE_FLAG_PARENT ( config, common); //TODO: here seems to be a name clash with the global "config" channel
NOBUG_CPP_DEFINE_FLAG_PARENT ( configfiles, config); //reading, writing, lookup configfiles
NOBUG_CPP_DEFINE_FLAG_PARENT ( configtyped, config); //values queried, errors
/** progress log, interfaces */
@ -142,6 +142,8 @@ NOBUG_CPP_DEFINE_FLAG_PARENT ( subsystem, common);
NOBUG_CPP_DEFINE_FLAG_PARENT ( pluginloader, common); //plugins loaded/unloaded/errors
/** progress log, external plugins*/
NOBUG_CPP_DEFINE_FLAG_PARENT ( plugins, progress);
/** base channel flag to track overall working of the render engine */
NOBUG_CPP_DEFINE_FLAG_PARENT ( render, logging);
/** base flag for software testing */
NOBUG_CPP_DEFINE_FLAG_PARENT ( test, logging);
/** base flag for syncronization logging */

View file

@ -98,6 +98,7 @@ namespace lib {
/** Activation of the handle by the managing service.
* @param impl the implementation object this handle is tied to
* @param whenDead functor to be invoked when reaching end-of-life
* @throw std::bad_alloc, in which case \c whenDead(impl) is invoked
*/
template<typename DEL>
Handle&

View file

@ -48,8 +48,10 @@
#define CONTROL_COMMAND_DEF_H
//#include "pre.hpp"
#include "lib/error.hpp"
#include "include/symbol.hpp"
#include "proc/control/command.hpp"
#include "proc/control/command-registry.hpp"
#include "proc/control/command-signature.hpp"
#include "proc/control/command-mutation.hpp"
#include "proc/control/command-closure.hpp"
@ -89,27 +91,47 @@ namespace control {
, UndoDefinition<SIG,MEM> // target type (this class) providing the implementation \c bindArg(Tuple<..>)
>
{
typedef typename FunctionSignature< function<SIG> >::Args BasicArgs;
typedef typename FunctionTypedef<MEM,BasicArgs>::Sig UndoCaptureSig;
typedef CommandSignature<SIG,MEM> CmdType;
typedef typename CmdType::OperateSig CommandOperationSig;
typedef typename CmdType::UndoOp_Sig UndoOperationSig;
typedef typename CmdType::CaptureSig UndoCaptureSig;
typedef function<CommandOperationSig> OperFunc;
typedef function<UndoOperationSig> UndoFunc;
typedef function<UndoCaptureSig> CaptFunc;
Command& prototype_;
OperFunc operFunctor_;
UndoFunc undoFunctor_;
CaptFunc captFunctor_;
UndoDefinition (Command& underConstruction, function<UndoCaptureSig>& undoCapOperation)
UndoDefinition (Command& underConstruction,
OperFunc& commandOperation,
CaptFunc& undoCapOperation)
: prototype_(underConstruction)
, operFunctor_(commandOperation)
, captFunctor_(undoCapOperation)
, undoFunctor_()
{
cout << showSizeof(undoCapOperation) << endl;
UNIMPLEMENTED ("re-fetch command definition and augment it with Functor for capturing Undo information");
}
template<typename SIG2>
UndoDefinition&
undoOperation (SIG2& how_to_Undo)
undoOperation (UndoOperationSig& how_to_Undo)
{
typedef typename UndoSignature<SIG2>::UndoOp_Sig UndoSig;
undoFunctor_ = UndoFunc (how_to_Undo);
REQUIRE (operFunctor_);
REQUIRE (undoFunctor_);
REQUIRE (captFunctor_);
function<UndoSig> opera3 (how_to_Undo);
UNIMPLEMENTED ("store actual Undo-Functor into the command definition held by the enclosing UndoDefinition instance");
CommandRegistry& registry = CommandRegistry::instance();
CommandImpl& completedDef = registry.newCommandImpl(operFunctor_
,undoFunctor_
,captFunctor_);
prototype_.activate(completedDef);
ENSURE (prototype_);
return *this;
}
@ -146,13 +168,12 @@ namespace control {
struct BasicDefinition
{
Command& prototype_;
function<SIG>& operation_;
BasicDefinition(Command& underConstruction, function<SIG>& operation)
: prototype_(underConstruction)
{
cout << showSizeof(operation) << endl;
UNIMPLEMENTED ("create new command object and store the operation functor");
}
, operation_(operation)
{ }
template<typename SIG2>
@ -162,8 +183,8 @@ namespace control {
typedef typename UndoSignature<SIG2>::CaptureSig UndoCapSig;
typedef typename BuildUndoDefType<UndoSignature<SIG2> >::Type SpecificUndoDefinition;
function<UndoCapSig> opera2 (how_to_capture_UndoState);
return SpecificUndoDefinition (prototype_, opera2);
function<UndoCapSig> captureOperation (how_to_capture_UndoState);
return SpecificUndoDefinition (prototype_, operation_, captureOperation);
}
};

View file

@ -96,18 +96,29 @@ namespace control {
}
/** search the command index for a definition
* @param cmdInstance using the definition to look up
* @return the ID used to register this definition
* or \c NULL in case of an "anonymous" command */
Symbol
findDefinition (Command const& cmdInstance)
{
UNIMPLEMENTED ("try to find a registration in the index for a given command instance");
}
size_t
index_size()
{
UNIMPLEMENTED ("number of defs in the index");
}
{
UNIMPLEMENTED ("number of defs in the index");
}
size_t
instance_count()
{
UNIMPLEMENTED ("number of active command impl instances");
}
{
UNIMPLEMENTED ("number of active command impl instances");
}
/** set up a new command implementation frame */

View file

@ -30,7 +30,9 @@
*/
#include "lib/util.hpp"
#include "lib/error.hpp"
#include "include/logging.h"
#include "proc/control/command.hpp"
#include "proc/control/command-def.hpp"
#include "proc/control/command-registry.hpp"
@ -39,16 +41,22 @@
//#include "proc/mobject/mobject.hpp"
//#include "proc/mobject/placement.hpp"
//#include <boost/format.hpp>
#include <boost/format.hpp>
#include <sstream>
#include <string>
using namespace lumiera;
using std::ostringstream;
using std::string;
//using boost::str;
using boost::format;
using boost::str;
using util::cStr;
namespace control {
LUMIERA_ERROR_DEFINE (INVALID_COMMAND, "Unknown or insufficiently defined command");
LUMIERA_ERROR_DEFINE (DUPLICATE_COMMAND, "Attempt to redefine an already existing command definition");
LUMIERA_ERROR_DEFINE (INVALID_ARGUMENTS, "Arguments provided for binding doesn't match stored command function parameters");
LUMIERA_ERROR_DEFINE (UNBOUND_ARGUMENTS, "Command mutation functor not yet usable, because arguments aren't bound");
LUMIERA_ERROR_DEFINE (MISSING_MEMENTO, "Undo functor not yet usable, because no undo state has been captured");
@ -58,20 +66,15 @@ namespace control {
Command::~Command() { }
/** @internal to be invoked by #fetchDef */
Command::Command (CommandImpl* pImpl)
{
Handle::activate (pImpl, CommandRegistry::killCommandImpl);
}
/** */
Command
Command::get (Symbol cmdID)
{
Command cmd = CommandRegistry::instance().queryIndex (cmdID);
static format fmt("Command definition \"%s\" not found");
if (!cmd)
throw lumiera::error::Invalid("Command definition not found", LUMIERA_ERROR_INVALID_COMMAND);
throw error::Invalid(str(fmt % cmdID), LUMIERA_ERROR_INVALID_COMMAND);
return cmd;
}
@ -85,12 +88,32 @@ namespace control {
if (cmd)
return cmd;
Command newDefinition (registry.newCommandImpl());
// create an empty definition, later to be activated
Command newDefinition;
return registry.track (cmdID, newDefinition);
} // return new or currently registered cmd...
/** @internal to be invoked by CommandDef
* @throw std::bad_alloc, in which case
* CommandRegistry::killCommandImpl is invoked */
Command&
Command::activate (CommandImpl& implFrame)
{
static format fmt_err("Command \"%s\" already defined");
static format fmt_ok("Command \"%s\" defined OK");
if (this->isValid())
throw error::Logic (str(fmt_err % *this), LUMIERA_ERROR_DUPLICATE_COMMAND);
_Handle::activate (&implFrame, CommandRegistry::killCommandImpl);
INFO (command, cStr(fmt_ok % *this));
return *this;
}
CommandDef
Command::storeDef (Symbol newCmdID)
{
@ -175,6 +198,34 @@ namespace control {
return isValid()
&& impl().canUndo();
}
/** diagnostics: shows the commandID, if any,
* and the degree of definition of this command */
Command::operator string() const
{
ostringstream repr;
repr << "Command";
////////////////////////////////////////////////////////////////////TODO do we need no-throw guarantee here?
Symbol id = CommandRegistry::instance().findCommand (*this);
if (id)
repr << "(\""<<id<<"\") ";
else
repr << "(_xxx_) ";
if (!isValid())
repr << "NIL";
else
if (canUndo())
repr << "{undo}";
else
if (canExec())
repr << "{exec}";
else
repr << "{def}";
return repr.str();
}

View file

@ -43,6 +43,7 @@
#include "lib/handle.hpp"
//#include <tr1/memory>
#include <string>
///////////////////////////////////////////TODO: define an C-API representation here, make the header multilingual!
@ -50,11 +51,13 @@
namespace control {
using std::string;
using lumiera::Symbol;
// using std::tr1::shared_ptr;
LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS); ///< Command functor not yet usable, because arguments aren't bound
LUMIERA_ERROR_DECLARE (INVALID_COMMAND); ///< Unknown or insufficiently defined command
LUMIERA_ERROR_DECLARE (DUPLICATE_COMMAND); ///< Attempt to redefine an already existing command definition
LUMIERA_ERROR_DECLARE (INVALID_ARGUMENTS); ///< Arguments provided for binding doesn't match stored command function parameters
@ -76,9 +79,9 @@ namespace control {
public:
/* === command registry === */
static Command& get (Symbol cmdID);
static bool remove (Symbol cmdID);
static bool undef (Symbol cmdID);
static Command get (Symbol cmdID);
static bool remove (Symbol cmdID);
static bool undef (Symbol cmdID);
CommandDef storeDef (Symbol newCmdID);
@ -100,6 +103,11 @@ namespace control {
HandlingPattern const& getDefaultHandlingPattern() const;
/* === command lifecycle === */
Command& activate (CommandImpl&);
template<typename TYPES>
void bindArg (Tuple<TYPES> const&);
@ -113,24 +121,17 @@ namespace control {
bool canExec() const;
bool canUndo() const;
operator string() const;
friend bool operator== (Command const&, Command const&);
protected:
static Command& fetchDef (Symbol cmdID);
static Command fetchDef (Symbol cmdID);
friend class CommandDef;
private:
/** Commands can only be created through the framework
* (by setting up an CommandDef), thus ensuring there's
* always a corresponding CommandImpl within the registry.
* @note the copy operations are public though
* @see Command#fetchDef
* @see CommandDef
*/
Command (CommandImpl* pImpl);
};
////////////////TODO currently just fleshing out the API....

View file

@ -58,6 +58,7 @@ namespace test {
// using lib::test::showSizeof;
using util::isSameObject;
using util::contains;
// using session::test::TestClip;
// using lumiera::P;
@ -97,6 +98,7 @@ namespace test {
standardUse();
definePrototype();
usePrototype();
preventDuplicates();
undef();
ASSERT (0 == command1::check_);
@ -138,7 +140,9 @@ namespace test {
ASSERT (!Command::get("test.command1.2"));
Command com = Command::get("test.command1.2");
ASSERT (!com);
ASSERT (contains (str(com), "test.command1.2"));
ASSERT (contains (str(com), "{def}"));
ASSERT (!com); ////////////////////TODO: mismatch: shall bool() < canExec() ????
ASSERT (!com.canUndo());
VERIFY_ERROR (UNBOUND_ARGUMENTS, com() );
@ -248,6 +252,20 @@ namespace test {
}
void
preventDuplicates()
{
ASSERT (CommandDef ("test.command1.1"));
VERIFY_ERROR (DUPLICATE_COMMAND, CommandDef ("test.command1.1").operation (command1::operate) );
ASSERT (CommandDef ("test.command1.2"));
VERIFY_ERROR (DUPLICATE_COMMAND, CommandDef ("test.command1.2").operation (command1::operate) );
ASSERT (CommandDef ("test.command1.3"));
VERIFY_ERROR (DUPLICATE_COMMAND, CommandDef ("test.command1.3").operation (command1::operate) );
ASSERT (CommandDef ("test.command1.4"));
VERIFY_ERROR (DUPLICATE_COMMAND, CommandDef ("test.command1.4").operation (command1::operate) );
}
void
undef()
{
@ -266,8 +284,15 @@ namespace test {
CommandDef unbelievable ("miracle");
ASSERT (!unbelievable);
Command miracle;
// but because the miracle isn't yet defined, any use throws
VERIFY_ERROR (INVALID_COMMAND, Command::get("miracle"));
VERIFY_ERROR (INVALID_COMMAND, miracle.bind("abracadabra"));
VERIFY_ERROR (INVALID_COMMAND, miracle.execSync());
VERIFY_ERROR (INVALID_COMMAND, miracle.undo());
VERIFY_ERROR (INVALID_COMMAND, miracle());
ASSERT (!miracle.canExec());
ASSERT (!miracle.canUndo());
ASSERT (!miracle);
ASSERT (Command::remove("test.command1.1"));
ASSERT (Command::remove("test.command1.2"));