Finished basic concept how to establish a current query focus (Ticket #403)
This commit is contained in:
parent
cdb84a9b16
commit
ce98bd9bca
6 changed files with 74 additions and 42 deletions
|
|
@ -37,6 +37,20 @@ namespace session {
|
|||
{ }
|
||||
|
||||
|
||||
/** */
|
||||
ScopePath&
|
||||
QueryFocus::currPath()
|
||||
{
|
||||
UNIMPLEMENTED ("dereference and access the current scope path");
|
||||
}
|
||||
|
||||
ScopePath const&
|
||||
QueryFocus::currPath() const
|
||||
{
|
||||
UNIMPLEMENTED ("dereference and access the current scope path");
|
||||
}
|
||||
|
||||
|
||||
/** discard any state and clear
|
||||
the current focus path */
|
||||
QueryFocus&
|
||||
|
|
@ -73,15 +87,16 @@ namespace session {
|
|||
|
||||
|
||||
/** cease to use \em this specific reference to the current frame.
|
||||
This operation immediately tries to re-access what is "current"
|
||||
and returns a new handle. But when the previously released reference
|
||||
was the last one, releasing it will cause the QueryFocusStack to pop,
|
||||
in which case we'll re-attach to the now uncovered previous stack top.
|
||||
This operation immediately tries to re-attach to what is "current"
|
||||
and readjusts the internal handle. But when the previously released
|
||||
reference was the last one, releasing it will cause the QueryFocusStack
|
||||
to pop, in which case we'll re-attach to the now uncovered previous stack top.
|
||||
*/
|
||||
QueryFocus
|
||||
QueryFocus&
|
||||
QueryFocus::pop()
|
||||
{
|
||||
|
||||
UNIMPLEMENTED ("pop, give up one reference, maybe drop stack top");
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace session {
|
|||
*/
|
||||
class QueryFocus
|
||||
{
|
||||
ScopePath scopes_;
|
||||
ScopePath scopes_; /////////////////////////////////////////////////////////////////TODO use intrusive pointer
|
||||
/////////////////////////////////////////////////////////////////////////////////////TODO how to integrate the ref-counting handle?
|
||||
|
||||
public:
|
||||
|
|
@ -54,10 +54,10 @@ namespace session {
|
|||
QueryFocus& reset ();
|
||||
QueryFocus& attach (Scope const&);
|
||||
static QueryFocus push (Scope const&);
|
||||
QueryFocus pop();
|
||||
QueryFocus& pop();
|
||||
|
||||
operator Scope() const { return scopes_.getLeaf(); }
|
||||
ScopePath currentPath() const { return scopes_; }
|
||||
operator Scope() const { return currPath().getLeaf(); }
|
||||
ScopePath currentPath() const { return currPath(); } ///< @note returns a copy
|
||||
|
||||
template<class MO>
|
||||
typename ScopeQuery<MO>::iterator
|
||||
|
|
@ -72,6 +72,10 @@ namespace session {
|
|||
{
|
||||
ScopeLocator::instance().explore<MO> (*this);
|
||||
}
|
||||
|
||||
private:
|
||||
ScopePath & currPath();
|
||||
ScopePath const& currPath() const;
|
||||
};
|
||||
///////////////////////////TODO currently just fleshing the API
|
||||
|
||||
|
|
|
|||
|
|
@ -24,33 +24,38 @@
|
|||
#ifndef MOBJECT_SESSION_SCOPE_LOCATOR_H
|
||||
#define MOBJECT_SESSION_SCOPE_LOCATOR_H
|
||||
|
||||
//#include "proc/mobject/mobject.hpp"
|
||||
#include "proc/mobject/session/scope.hpp"
|
||||
#include "proc/mobject/placement.hpp"
|
||||
#include "proc/mobject/session/scope-query.hpp"
|
||||
#include "proc/mobject/placement.hpp"
|
||||
#include "lib/singleton.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <tr1/memory>
|
||||
//#include <vector>
|
||||
//#include <string>
|
||||
|
||||
//using std::vector;
|
||||
//using std::string;
|
||||
|
||||
namespace mobject {
|
||||
namespace session {
|
||||
|
||||
using std::tr1::shared_ptr;
|
||||
using boost::scoped_ptr;
|
||||
using util::cStr;
|
||||
|
||||
class QueryFocusStack;
|
||||
class ScopePath;
|
||||
|
||||
|
||||
class QueryFocusStack; //////TODO better include?
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Singleton service establishing a link to relate
|
||||
* any compound of nested placement scopes to the current session
|
||||
* and the \em current focus for querying and exploring this structure.
|
||||
* While it is OK to use this service directly, clients usually would
|
||||
* prefer to use QueryFocus as a frontend.
|
||||
*
|
||||
* ScopeLocator is the access point both to the current query scope location
|
||||
* (as maintained with the help of the QueryFocusStack) and allows to explore
|
||||
* the current session data structures (building on a QueryResolver service
|
||||
* exposed by the session).
|
||||
*
|
||||
* @note in its current form (11/09), ScopeLocator is deliberately <b>not threadsafe</b>
|
||||
*/
|
||||
class ScopeLocator
|
||||
{
|
||||
scoped_ptr<QueryFocusStack> focusStack_;
|
||||
|
|
@ -58,7 +63,7 @@ namespace session {
|
|||
public:
|
||||
static lib::Singleton<ScopeLocator> instance;
|
||||
|
||||
QueryFocus currFocus();
|
||||
ScopePath& currPath();
|
||||
|
||||
template<typename MO>
|
||||
typename ScopeQuery<MO>::iterator
|
||||
|
|
@ -76,12 +81,11 @@ namespace session {
|
|||
private:
|
||||
QueryResolver const& theResolver();
|
||||
};
|
||||
///////////////////////////TODO currently just fleshing the API
|
||||
|
||||
|
||||
|
||||
|
||||
/** use the currently installed contents-resolving facility
|
||||
/** use the contents-resolving facility exposed by the session
|
||||
* to enumerate the contents (children) of the given scope
|
||||
*/
|
||||
template<typename MO>
|
||||
|
|
@ -92,7 +96,7 @@ namespace session {
|
|||
}
|
||||
|
||||
|
||||
/** use the currently installed contents-resolving facility
|
||||
/** use the contents-resolving facility exposed by the session
|
||||
* to discover depth-first any object within this scope
|
||||
*/
|
||||
template<typename MO>
|
||||
|
|
|
|||
|
|
@ -88,9 +88,18 @@ namespace session {
|
|||
}
|
||||
|
||||
|
||||
/** TODO */
|
||||
QueryFocus
|
||||
ScopeLocator::currFocus()
|
||||
/** establishes the \em current query focus location.
|
||||
* Relies on the state of the QueryFocusStack.
|
||||
* If there is no current focus location, a new
|
||||
* one is created, referring to the root Scope.
|
||||
* @return the current path corresponding to the
|
||||
* most recently used QueryFocus, which is
|
||||
* actually still referred from somewhere.
|
||||
* @note may cause the QueryFocusStack to pop
|
||||
* path entries no longer in use.
|
||||
*/
|
||||
ScopePath&
|
||||
ScopeLocator::currPath()
|
||||
{
|
||||
UNIMPLEMENTED ("how to access and handle the current focus");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ namespace test {
|
|||
manipulate_subFocus()
|
||||
{
|
||||
#ifdef false ////////////////////////////////////////////////////////////////////////////////TICKET 384
|
||||
QueryFocus original;
|
||||
QueryFocus original; // automatically attaches to current stack top
|
||||
uint num_refs = original.ref_count();
|
||||
ASSERT (num_refs > 1);
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ namespace test {
|
|||
ASSERT ( 1 == subF.ref_count());
|
||||
ASSERT (num_refs == original.ref_count());
|
||||
|
||||
{
|
||||
{ // temporarily creating an independent focus attached differently
|
||||
QueryFocus subF2 = QueryFocus::push(Scope(subF).getParent());
|
||||
ASSERT (subF2 != subF);
|
||||
ASSERT (subF == original);
|
||||
|
|
@ -145,13 +145,13 @@ namespace test {
|
|||
}
|
||||
cout << string(subF2) << "<<<--discovery exhausted" << endl;
|
||||
|
||||
subF2.pop();
|
||||
subF2.pop(); // releasing this focus and re-attaching to what's on stack top
|
||||
cout << string(subF2) << "<<<--after pop()" << endl;
|
||||
ASSERT (subF2 == subF);
|
||||
ASSERT (2 == subF2.ref_count());
|
||||
ASSERT (2 == subF2.ref_count()); // both are now attached to the same path
|
||||
ASSERT (2 == subF.ref_count());
|
||||
}
|
||||
// subF2 went out of scope, but no auto-pop happens
|
||||
// subF2 went out of scope, but no auto-pop happens (because subF is still there)
|
||||
cout << string(subF) << endl;
|
||||
|
||||
ASSERT ( 1 == subF.ref_count());
|
||||
|
|
|
|||
|
|
@ -3469,7 +3469,7 @@ For decoupling the query invocation from the facility actually processing the qu
|
|||
See also the notes on &rarr; QueryImplProlog
|
||||
</pre>
|
||||
</div>
|
||||
<div title="QueryFocus" modifier="Ichthyostega" modified="200911192106" created="200910140244" tags="def spec img" changecount="21">
|
||||
<div title="QueryFocus" modifier="Ichthyostega" modified="200911201829" created="200910140244" tags="def spec img" changecount="28">
|
||||
<pre>When querying contents of the session or sub-containers within the session, the QueryFocus follows the current point-of-query. As such queries can be issued to explore the content of container-like objects holding other MObjects, the focus is always attached to a container, which also acts as [[scope|PlacementScope]] for the contained objects. QueryFocus is an implicit state (the current point of interrest). This sate especially remembers the path down from the root of the HighLevelModel, which was used to access the current scope. Because this path constitutes a hierarchy of scopes, it can be relevant for querying and resolving placement properties. (&rarr; SessionStructureQuery)
|
||||
|
||||
!provided operations
|
||||
|
|
@ -3481,10 +3481,10 @@ See also the notes on &rarr; QueryImplProlog
|
|||
* (typed) content discovery query on the current scope
|
||||
[>img[Scope Locating|uml/fig136325.png]]
|
||||
!!!relation to Scope
|
||||
There is a tight integration with PlacementScope through the ScopeLocator, which establishes the //current scope.// But QueryFocus is more of a //binding// &mdash; it links or focusses the current state into a specific scope with a ScopePath in turn depending on this current state. Thus, while Scope is just a passive container allowing to locate and navigate, QueryFocus by virtue of this binding allows to [[Query]] at this current location.
|
||||
There is a tight integration with PlacementScope through the ScopeLocator, which establishes the //current focus.// But while the [[scope|PlacementScope]] just decorates the placement defining a scope (called //&raquo;scope top&laquo;//), QueryFocus is more of a //binding// &mdash; it links or focusses the current state into a specific scope with a ScopePath in turn depending on this current state. Thus, while Scope is just a passive container allowing to locate and navigate, QueryFocus by virtue of this binding allows to [[Query]] at this current location.
|
||||
|
||||
!implementation notes
|
||||
we provide a static access API, meaning that there is a singleton (the ScopeLocator) behind the scenes, which manages the mentioned scope stack. Moreover, there is an link to the current session. But this link is kept opaque; it works by the current session exposing an [[query service|QueryResolver]], while QueryFocus doesn't rely on knowledge about the session, allowing the focus to be unit tested.
|
||||
we provide a static access API, meaning that there is a singleton (the ScopeLocator) behind the scenes, which holds the mentioned scope stack. The current focus stack top, i.e. the current ScopePath is managed through an ref-counting handle embedded into each QueryFocus instance. Thus, effectively QueryFocus is an frontend object for accessing this state. Moreover, embedded into ScopeLocator, there is an link to the current session. But this link is kept opaque; it works by the current session exposing an [[query service|QueryResolver]], while QueryFocus doesn't rely on knowledge about the session, allowing the focus to be unit tested.
|
||||
|
||||
The stack of scopes must not be confused with the ScopePath. Each single frame on the stack is a QueryFocus and as such contains a current ScopePath. The purpose of the stack is to make the scope handling mostly transparent; especially this stack allows to write dedicated query functions directed at a given object: they work by pushing and then navigating to the object to use as starting point for the query, i.e. the //current scope.//
|
||||
|
||||
|
|
@ -3916,15 +3916,15 @@ Later on we expect a distinct __query subsystem__ to emerge, presumably embeddin
|
|||
<div title="STypeManager" modifier="Ichthyostega" created="200809220230" changecount="1">
|
||||
<pre>A facility allowing the Proc-Layer to work with abstracted [[media stream types|StreamType]], linking (abstract or opaque) [[type tags|StreamTypeDescriptor]] to an [[library|MediaImplLib]], which provides functionality for acutally dealing with data of this media stream type. Thus, the stream type manager is a kind of registry of all the external libraries which can be bridged and accessed by Lumiera (for working with media data, that is). The most basic set of libraries is instelled here automatically at application start, most notably the [[GAVL]] library for working with uncompressed video and audio data. //Later on, when plugins will introduce further external libraries, these need to be registered here too.//</pre>
|
||||
</div>
|
||||
<div title="ScopeLocator" modifier="Ichthyostega" modified="200911192150" created="200911192145" tags="def SessionLogic" changecount="2">
|
||||
<pre>A link to relate a compound of [[nested placement scopes|PlacementScope]] to the //current// session and the //current// [[focus for querying|QueryFocus]] and exploring the structure. ScopeLocator is a singleton service, allowing to ''explore'' a [[Placement]] as a scope, i.e. discover any other placements within this scope, and allowing to locate the position of this scope by navigating the ScopePath up to finally reach the root scope of the HighLevelModel.
|
||||
<div title="ScopeLocator" modifier="Ichthyostega" modified="200911202035" created="200911192145" tags="def SessionLogic" changecount="10">
|
||||
<pre>A link to relate a compound of [[nested placement scopes|PlacementScope]] to the //current// session and the //current//&nbsp; [[focus for querying|QueryFocus]] and exploring the structure. ScopeLocator is a singleton service, allowing to ''explore'' a [[Placement]] as a scope, i.e. discover any other placements within this scope, and allowing to locate the position of this scope by navigating up the ScopePath finally to reach the root scope of the HighLevelModel.
|
||||
|
||||
In the general case, this user visible model of the [[objects|MObject]] within the session allows for more than tree-like associations, as a given [[Sequence|EDL]] might be bound into multiple [[timelines|Timeline]]. Effectively, this makes the ScopePath context dependent. The ScopeLocator is the point where the strictly tree-like hierarchy of placements is connected to this more elaborate scope and path structure.
|
||||
In the general case, this user visible high-level-model of the [[objects|MObject]] within the session allows for more than tree-like associations, as a given [[Sequence|EDL]] might be bound into multiple [[timelines|Timeline]]. Effectively, this makes the ScopePath context dependent. The ScopeLocator is the point where the strictly tree-like hierarchy of placements is connected to this more elaborate scope and path structure. To this end, ScopeLocator maintaines a QueryFocusStack, to keep track of the current location in focus, in cooperation with the QueryFocus objects used by client code.
|
||||
&rarr; see BindingScopeProblem
|
||||
&rarr; see TimelineSequences
|
||||
|
||||
!!a note about concurrency
|
||||
While there //is// a "current state" involved, the effect of concurrent access deliberately remains unspecified, because it is expected to be serialised on a higher level. If this assumption were to break, then probably the ScopeLocator will involve some thread local state.
|
||||
While there //is// a "current state" involved, the effect of concurrent access deliberately remains unspecified, because access is expected to be serialised on a higher level. If this assumption were to break, then probably the ScopeLocator would involve some thread local state.
|
||||
</pre>
|
||||
</div>
|
||||
<div title="Session" modifier="Ichthyostega" modified="200911071800" created="200712100525" tags="def SessionLogic" changecount="8">
|
||||
|
|
|
|||
Loading…
Reference in a new issue