implement a stack of ScopePath frames

This commit is contained in:
Fischlurch 2009-11-22 04:36:14 +01:00
parent 665eed5f1b
commit d90812e64b
3 changed files with 135 additions and 2 deletions

View file

@ -26,12 +26,17 @@
//#include "proc/mobject/mobject.hpp"
//#include "proc/mobject/placement.hpp"
#include "proc/mobject/session/scope-path.hpp"
//#include <vector>
//#include <string>
#include <boost/noncopyable.hpp>
#include <list>
//using std::vector;
//using std::string;
using std::list;
namespace mobject {
namespace session {
@ -42,13 +47,117 @@ namespace session {
* TODO type comment
*/
class QueryFocusStack
: boost::noncopyable
{
public:
std::list<ScopePath> paths_;
public:
QueryFocusStack()
: paths_()
{
openDefaultFrame();
}
bool empty() const;
size_t size() const;
ScopePath& push (Scope const&);
ScopePath& top ();
void pop_unused ();
private:
void openDefaultFrame();
};
///////////////////////////TODO currently just fleshing the API
bool
QueryFocusStack::empty() const
{
return paths_.empty();
}
size_t
QueryFocusStack::size() const
{
return paths_.size();
}
/** Open a new path frame, pushing down the current frame.
* The new frame tries to locate the given start scope
* and navigates to this position.
* @note EXCEPTION_STRONG guarantee
* @return reference to the newly created path on top
* @throw error::Invalid if newStartPoint isn't locatable
*/
ScopePath&
QueryFocusStack::push (Scope const& newStartPoint)
{
ScopePath newPathFrame (newStartPoint); // may throw
ENSURE (newPathFrame.isValid() || newStartPoint.isRoot());
paths_.push_back (newPathFrame);
ENSURE (0 < size());
return paths_.back();
}
/** @return the topmost path frame actually in use
* @note may invoke #pop_unused()
* @note EXCEPTON_FREE ///////TODO prove!
*/
ScopePath&
QueryFocusStack::top ()
{
if ( 0 == size()
|| 0 == paths_.back().ref_count()
)
pop_unused();
ENSURE (!empty());
ENSURE (!paths_.back().empty());
return paths_.back();
}
/** investigate the stack top and discard any path frames
* which aren't referred anymore (as indicated by their
* ScopePath#use_count(). After executing this function
* the topmost frame is either in use, or a new default
* frame has been created at the bottom of an empty stack.
* @note EXCEPTON_FREE ///////TODO prove!
*/
void
QueryFocusStack::pop_unused ()
{
while (size() && (0 == paths_.back().ref_count()))
paths_.pop_back();
if (0 == size())
openDefaultFrame();
ENSURE (!empty());
ENSURE (!paths_.back().empty());
}
/** @internal open a default path frame at the bottom
* of an empty stack, locating to current model root
* @note EXCEPTON_FREE ///////TODO prove!
*/
void
QueryFocusStack::openDefaultFrame()
{
REQUIRE (0 == size());
paths_.resize(1);
}
}} // namespace mobject::session
#endif

View file

@ -21,6 +21,7 @@
* *****************************************************/
#include "include/logging.h"
#include "proc/mobject/session/scope-path.hpp"
#include "proc/mobject/session/scope-locator.hpp"
#include "proc/mobject/session/session-service-explore-scope.hpp"
@ -113,7 +114,7 @@ namespace session {
ScopePath::~ScopePath()
{
WARN_IF (refcount_, "Destroying a scope path frame with ref-count=%u", refcount_);
WARN_IF (refcount_, session, "Destroying a scope path frame with ref-count=%lu", refcount_);
}

View file

@ -149,6 +149,9 @@ namespace session {
friend bool operator== (ScopePath const&, ScopePath const&);
friend void intrusive_ptr_add_ref (ScopePath*);
friend void intrusive_ptr_release (ScopePath*);
/* == mutations == */
void clear();
@ -182,6 +185,26 @@ namespace session {
}
/** management function for boost::intrusive_ptr
* to be picked up by ADL
*/
void
intrusive_ptr_add_ref (ScopePath* pathFrame)
{
REQUIRE (pathFrame);
++(pathFrame->refcount_);
}
void
intrusive_ptr_release (ScopePath* pathFrame)
{
REQUIRE (pathFrame);
if (0 < pathFrame->refcount_)
--(pathFrame->refcount_);
}
inline size_t
ScopePath::ref_count() const
{