From d90812e64b6c9bea6a45b14aa25a6ac9ce935dcd Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 22 Nov 2009 04:36:14 +0100 Subject: [PATCH] implement a stack of ScopePath frames --- .../mobject/session/query-focus-stack.hpp | 111 +++++++++++++++++- src/proc/mobject/session/scope-path.cpp | 3 +- src/proc/mobject/session/scope-path.hpp | 23 ++++ 3 files changed, 135 insertions(+), 2 deletions(-) diff --git a/src/proc/mobject/session/query-focus-stack.hpp b/src/proc/mobject/session/query-focus-stack.hpp index 499bf22d7..0c6c95413 100644 --- a/src/proc/mobject/session/query-focus-stack.hpp +++ b/src/proc/mobject/session/query-focus-stack.hpp @@ -26,12 +26,17 @@ //#include "proc/mobject/mobject.hpp" //#include "proc/mobject/placement.hpp" +#include "proc/mobject/session/scope-path.hpp" //#include //#include +#include +#include //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 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 diff --git a/src/proc/mobject/session/scope-path.cpp b/src/proc/mobject/session/scope-path.cpp index 5a2c7291b..f464cc7d9 100644 --- a/src/proc/mobject/session/scope-path.cpp +++ b/src/proc/mobject/session/scope-path.cpp @@ -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_); } diff --git a/src/proc/mobject/session/scope-path.hpp b/src/proc/mobject/session/scope-path.hpp index a650ff2a4..4f985e4a9 100644 --- a/src/proc/mobject/session/scope-path.hpp +++ b/src/proc/mobject/session/scope-path.hpp @@ -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 {