implemented the mechanism for dispatch-to-concrete resolution
This commit is contained in:
parent
572f26edc8
commit
f70f8c4e4a
5 changed files with 96 additions and 27 deletions
|
|
@ -62,7 +62,7 @@ namespace mobject { ///////////////////////////////////////////TODO: shouldn't t
|
||||||
*/
|
*/
|
||||||
class PlacementIndex
|
class PlacementIndex
|
||||||
: public session::QueryResolver ////////TODO: really inherit here?
|
: public session::QueryResolver ////////TODO: really inherit here?
|
||||||
, boost::noncopyable
|
// , boost::noncopyable ////////TODO : where to put the "noncopyable" base
|
||||||
{
|
{
|
||||||
class Table;
|
class Table;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,45 +22,91 @@
|
||||||
|
|
||||||
|
|
||||||
#include "proc/mobject/session/query-resolver.hpp"
|
#include "proc/mobject/session/query-resolver.hpp"
|
||||||
//#include "proc/mobject/session/track.hpp"
|
#include "lib/multifact-arg.hpp"
|
||||||
//#include "proc/mobject/placement.hpp"
|
|
||||||
//#include "proc/mobject/session/mobjectfactory.hpp"
|
|
||||||
//#include "proc/asset/track.hpp"
|
|
||||||
|
|
||||||
namespace mobject {
|
namespace mobject {
|
||||||
namespace session {
|
namespace session {
|
||||||
|
|
||||||
|
using lib::factory::MultiFact;
|
||||||
|
using lib::factory::BuildRefcountPtr;
|
||||||
|
|
||||||
|
|
||||||
/* generate vtables here */
|
/* generate vtables here... */
|
||||||
|
|
||||||
Goal::~Goal() { }
|
Goal::~Goal() { }
|
||||||
|
|
||||||
QueryResolver::~QueryResolver() { }
|
|
||||||
|
|
||||||
Resolution::~Resolution() { }
|
Resolution::~Resolution() { }
|
||||||
|
|
||||||
|
QueryResolver::~QueryResolver() { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef Goal::QueryID const& QID;
|
||||||
|
|
||||||
|
/** we're going to use QueryID as Map key... */
|
||||||
|
inline bool
|
||||||
|
operator< (QID q1, QID q2)
|
||||||
|
{
|
||||||
|
return (q1.kind < q2.kind)
|
||||||
|
|| (q1.kind == q2.kind
|
||||||
|
&& q1.type < q2.type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* == dispatch to resolve typed queries == */
|
||||||
|
|
||||||
|
/** factory used as dispatcher table
|
||||||
|
* for resolving typed queries */
|
||||||
|
typedef MultiFact< Resolution(Goal&) // nominal signature of fabrication
|
||||||
|
, Goal::QueryID // select resolution function by kind-of-Query
|
||||||
|
, BuildRefcountPtr // wrapper: manage result set by smart-ptr
|
||||||
|
> DispatcherTable; //
|
||||||
|
|
||||||
struct QueryDispatcher
|
struct QueryDispatcher
|
||||||
|
: DispatcherTable
|
||||||
{
|
{
|
||||||
|
|
||||||
|
PReso
|
||||||
|
handle (Goal& query)
|
||||||
|
{
|
||||||
|
QID qID = query.getQID();
|
||||||
|
ENSURE (contains (qID));
|
||||||
|
|
||||||
|
return (*this) (qID, query);
|
||||||
|
} //qID picks the resolution function
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QueryResolver::QueryResolver ()
|
QueryResolver::QueryResolver ()
|
||||||
: dispatcher_(new QueryDispatcher)
|
: dispatcher_(new QueryDispatcher)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
/** TODO??? */
|
/** @par implementation
|
||||||
|
* For actually building a result set, the QueryResolver base implementation
|
||||||
|
* uses an embedded dispatcher table. The concrete query resolving facilities,
|
||||||
|
* when implementing the QueryResolver interface, are expected to register
|
||||||
|
* individual resolution functions into this QueryDispatcher table.
|
||||||
|
* Whenever issuing a Goal, a suitable resolution function is picked
|
||||||
|
* based on the Goal::QueryID, which contains an embedded type code.
|
||||||
|
* Thus, the individual resolution function can (re)establish a
|
||||||
|
* typed context and downcast the Goal appropriately
|
||||||
|
*/
|
||||||
PReso
|
PReso
|
||||||
QueryResolver::issue (Goal& query) const
|
QueryResolver::issue (Goal& query) const
|
||||||
{
|
{
|
||||||
|
TODO ("ensure proper initialisation");
|
||||||
|
|
||||||
if (!canHandleQuery (query.getQID()))
|
if (!canHandleQuery (query.getQID()))
|
||||||
throw lumiera::error::Invalid ("unable to resolve this kind of query"); ////TICKET #197
|
throw lumiera::error::Invalid ("unable to resolve this kind of query"); ////TICKET #197
|
||||||
|
|
||||||
UNIMPLEMENTED ("dispatch-mechanism for re-discovering specific type-context");
|
return dispatcher_->handle(query);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include "lib/iter-adapter.hpp"
|
#include "lib/iter-adapter.hpp"
|
||||||
#include "lib/util.hpp"
|
#include "lib/util.hpp"
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
#include <boost/scoped_ptr.hpp>
|
#include <boost/scoped_ptr.hpp>
|
||||||
#include <tr1/memory>
|
#include <tr1/memory>
|
||||||
//#include <vector>
|
//#include <vector>
|
||||||
|
|
@ -43,6 +44,7 @@ namespace mobject {
|
||||||
namespace session {
|
namespace session {
|
||||||
|
|
||||||
using util::unConst;
|
using util::unConst;
|
||||||
|
using boost::noncopyable;
|
||||||
|
|
||||||
|
|
||||||
class Goal;
|
class Goal;
|
||||||
|
|
@ -60,6 +62,7 @@ namespace session {
|
||||||
* Query ABC
|
* Query ABC
|
||||||
*/
|
*/
|
||||||
class Goal
|
class Goal
|
||||||
|
: noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Goal() ;
|
virtual ~Goal() ;
|
||||||
|
|
@ -78,6 +81,12 @@ namespace session {
|
||||||
QueryID getQID() { return id_; }
|
QueryID getQID() { return id_; }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single Solution, possibly part of a result set.
|
||||||
|
* A pointer-like object, usually to be down-casted
|
||||||
|
* to a specifically typed Query::Cursor
|
||||||
|
* @see Resolution
|
||||||
|
*/
|
||||||
class Result
|
class Result
|
||||||
: public lib::BoolCheckable<Result>
|
: public lib::BoolCheckable<Result>
|
||||||
{
|
{
|
||||||
|
|
@ -117,6 +126,15 @@ namespace session {
|
||||||
* the specific result types of issued queries */
|
* the specific result types of issued queries */
|
||||||
typedef lib::TypedContext<Goal::Result> ResultType;
|
typedef lib::TypedContext<Goal::Result> ResultType;
|
||||||
|
|
||||||
|
template<typename RES>
|
||||||
|
inline size_t
|
||||||
|
getResultTypeID() ///< @return unique ID denoting result type RES
|
||||||
|
{
|
||||||
|
return ResultType::ID<RES>::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO type comment
|
* TODO type comment
|
||||||
|
|
@ -129,7 +147,7 @@ namespace session {
|
||||||
static QueryID
|
static QueryID
|
||||||
defineQueryTypeID ()
|
defineQueryTypeID ()
|
||||||
{
|
{
|
||||||
QueryID id = {Goal::GENERIC, ResultType::ID<RES>::get()};
|
QueryID id = {Goal::GENERIC, getResultTypeID<RES>() };
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,6 +156,7 @@ namespace session {
|
||||||
: Goal (defineQueryTypeID())
|
: Goal (defineQueryTypeID())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
/* results retrieval */
|
/* results retrieval */
|
||||||
class Cursor
|
class Cursor
|
||||||
: public Goal::Result
|
: public Goal::Result
|
||||||
|
|
@ -156,7 +175,8 @@ namespace session {
|
||||||
|
|
||||||
typedef lib::IterAdapter<Cursor,PReso> iterator;
|
typedef lib::IterAdapter<Cursor,PReso> iterator;
|
||||||
|
|
||||||
iterator operator() (QueryResolver const& resolver);
|
iterator
|
||||||
|
operator() (QueryResolver const& resolver);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -166,6 +186,7 @@ namespace session {
|
||||||
* of an individual query resolution
|
* of an individual query resolution
|
||||||
*/
|
*/
|
||||||
class Resolution
|
class Resolution
|
||||||
|
: noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Goal::Result Result;
|
typedef Goal::Result Result;
|
||||||
|
|
@ -195,9 +216,11 @@ namespace session {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Interface: a facility for resolving (some) queries
|
||||||
* TODO type comment
|
* TODO type comment
|
||||||
*/
|
*/
|
||||||
class QueryResolver
|
class QueryResolver
|
||||||
|
: noncopyable
|
||||||
{
|
{
|
||||||
boost::scoped_ptr<QueryDispatcher> dispatcher_;
|
boost::scoped_ptr<QueryDispatcher> dispatcher_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,23 +54,23 @@ namespace test {
|
||||||
|
|
||||||
|
|
||||||
template<typename TY>
|
template<typename TY>
|
||||||
class DummySolution;
|
class DummySolutions;
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
class DummySolution<int>
|
class DummySolutions<int>
|
||||||
{
|
{
|
||||||
int resNr_;
|
int resNr_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DummySolution() : resNr_(7) {}
|
DummySolutions() : resNr_(7) {}
|
||||||
|
|
||||||
int* next () { --resNr_; return &resNr_; }
|
int* next () { --resNr_; return &resNr_; }
|
||||||
bool exhausted() { return bool(resNr_); }
|
bool exhausted() { return bool(resNr_); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
class DummySolution<string>
|
class DummySolutions<string>
|
||||||
: DummySolution<int>
|
: DummySolutions<int>
|
||||||
{
|
{
|
||||||
string currentText_;
|
string currentText_;
|
||||||
|
|
||||||
|
|
@ -79,7 +79,7 @@ namespace test {
|
||||||
next ()
|
next ()
|
||||||
{
|
{
|
||||||
static const char* lumi ="Lumiera";
|
static const char* lumi ="Lumiera";
|
||||||
currentText_ = string (lumi + *DummySolution<int>::next());
|
currentText_ = string (lumi + *DummySolutions<int>::next());
|
||||||
return ¤tText_;
|
return ¤tText_;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -88,7 +88,7 @@ namespace test {
|
||||||
struct DummyResultSet
|
struct DummyResultSet
|
||||||
: Resolution
|
: Resolution
|
||||||
{
|
{
|
||||||
DummySolution<TY> solution_;
|
DummySolutions<TY> solutions_;
|
||||||
|
|
||||||
typedef typename Query<TY>::Cursor Cursor;
|
typedef typename Query<TY>::Cursor Cursor;
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ namespace test {
|
||||||
prepareResolution()
|
prepareResolution()
|
||||||
{
|
{
|
||||||
Cursor cursor;
|
Cursor cursor;
|
||||||
cursor.pointAt (solution_.next());
|
cursor.pointAt (solutions_.next());
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,10 +105,10 @@ namespace test {
|
||||||
{
|
{
|
||||||
Cursor& cursor = static_cast<Cursor&> (pos);
|
Cursor& cursor = static_cast<Cursor&> (pos);
|
||||||
|
|
||||||
if (solution_.exhausted())
|
if (solutions_.exhausted())
|
||||||
cursor.point_at (0);
|
cursor.point_at (0);
|
||||||
else
|
else
|
||||||
cursor.point_at (solution_.next());
|
cursor.point_at (solutions_.next());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ namespace test {
|
||||||
bool
|
bool
|
||||||
wantResultType (Goal::QueryID qID) const
|
wantResultType (Goal::QueryID qID) const
|
||||||
{
|
{
|
||||||
return qID.type == ResultType::ID<TY>::get();
|
return qID.type == getResultTypeID<TY>();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5562,9 +5562,9 @@ Using transitions is a very basic task and thus needs viable support by the GUI.
|
||||||
Because of this experience, ichthyo wants to support a more general case of transitions, which have N output connections, behave similar to their "simple" counterpart, but leave out the mixing step. As a plus, such transitions can be inserted at the source ports of N clips or between any intermediary or final output pipes as well. Any transition processor capable of handling this situation should provide some flag, in order to decide if he can be placed in such a manner. (wichin the builder, encountering a inconsistently placed transition is just an [[building error|BuildingError]])
|
Because of this experience, ichthyo wants to support a more general case of transitions, which have N output connections, behave similar to their "simple" counterpart, but leave out the mixing step. As a plus, such transitions can be inserted at the source ports of N clips or between any intermediary or final output pipes as well. Any transition processor capable of handling this situation should provide some flag, in order to decide if he can be placed in such a manner. (wichin the builder, encountering a inconsistently placed transition is just an [[building error|BuildingError]])
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
<div title="TypedQueryProblem" modifier="Ichthyostega" modified="200910231708" created="200910231618" tags="Rules dynamic" changecount="9">
|
<div title="TypedQueryProblem" modifier="Ichthyostega" modified="200910301629" created="200910231618" tags="Rules dynamic" changecount="10">
|
||||||
<pre>//the problem of processing specifically typed queries without tying query and QueryResolver.//<br/>This problem can be seen as a instance of the problematic situation encountered with most visitation schemes: we want entities and tools (visitors) to work together, without being forced to commit to a pre-defined table of operations. In the situation at hand here, we want //some entities// &mdash; which we don't know &mdash; to issue //some queries// &mdash; which we don't know either. Obviously, such a problem can be solved only by controlling the scope of this incomplete knowledge, and the sequence in time of building it.
|
<pre>//the problem of processing specifically typed queries without tying query and QueryResolver.//<br/>This problem can be seen as a instance of the problematic situation encountered with most visitation schemes: we want entities and tools (visitors) to work together, without being forced to commit to a pre-defined table of operations. In the situation at hand here, we want //some entities// &mdash; which we don't know &mdash; to issue //some queries// &mdash; which we don't know either. Obviously, such a problem can be solved only by controlling the scope of this incomplete knowledge, and the sequence in time of building it.
|
||||||
Thus, to re-state the problem more specifically, we want the //definition//&nbsp; of the entities to be completely separate of those concerning the details of the query resolution mechanism, so to be able to design, reason, verify and extend each one without being forced into concern about the details of the respective other side. So, the buildup of the combined structure has to be postponed &mdash; assuring it //has//&nbsp; happened at the point it's operations are required.
|
Thus, to re-state the problem more specifically, we want the //definition//&nbsp; of the entities to be completely separate of those definitions concerning the details of the query resolution mechanism, so to be able to design, reason, verify and extend each one without being forced into concern about the details of the respective other side. So, the buildup of the combined structure has to be postponed &mdash; assuring it //has//&nbsp; happened at the point it's operations are required.
|
||||||
|
|
||||||
!Solution Stages
|
!Solution Stages
|
||||||
* in ''static scope'' (while compiling), just a {{{Query<TY>}}} gets mentioned.<br/>As this is the only chance for driving a specifically typed context, we need to prepare a registration mechanism, to allow for //remembering//&nbsp; this context later.
|
* in ''static scope'' (while compiling), just a {{{Query<TY>}}} gets mentioned.<br/>As this is the only chance for driving a specifically typed context, we need to prepare a registration mechanism, to allow for //remembering//&nbsp; this context later.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue