From 666d57f6ef2811a1e463ed78808793f9d279bca2 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 4 Jun 2010 04:35:40 +0200 Subject: [PATCH] code up the obvious part of the AdviceSystem implementation --- src/lib/advice.hpp | 32 ++++++++++++---- src/lib/advice/advice.cpp | 80 +++++++++++++++++++++++++++++++++------ src/lib/advice/index.hpp | 4 +- 3 files changed, 96 insertions(+), 20 deletions(-) diff --git a/src/lib/advice.hpp b/src/lib/advice.hpp index 29a20d664..0ef5ede28 100644 --- a/src/lib/advice.hpp +++ b/src/lib/advice.hpp @@ -171,7 +171,6 @@ namespace advice { protected: void publishProvision (PointOfAdvice*); void discardSolutions (); - void publishBindingChange(); void publishRequestBindingChange(); void registerRequest(); @@ -240,11 +239,12 @@ namespace advice { defineBinding (Literal topic) { setBindingPattern (Binding(topic).addTypeGuard()); - publishBindingChange(); + maybe_rePublish(); } private: PointOfAdvice* storeCopy (AD const& advice_given); + void maybe_rePublish (); }; @@ -289,12 +289,29 @@ namespace advice { @throw error::External on allocation problems, plus anything the advice data may throw during copy construction. */ template - PointOfAdvice* + inline PointOfAdvice* Provision::storeCopy (AD const& advice_given) - { - typedef ActiveProvision Holder; - return new(getBuffer(sizeof(Holder))) Holder (*this, advice_given); - } + { + typedef ActiveProvision Holder; + return new(getBuffer(sizeof(Holder))) Holder (*this, advice_given); + } + + + /** @internal in case we've already published this provision, + * we temporarily need a new provision entry, to allow the + * AdviceSystem implementation to rewrite the internal index + */ + template + inline void + Provision::maybe_rePublish () + { + typedef const ActiveProvision AdviceProvision; + AdviceProvision* solution = static_cast (getSolution (*this)); + + if (solution) // create copy of the data holder, using the new binding + publishProvision (storeCopy (solution->getAdvice())); + } + @@ -346,6 +363,7 @@ namespace advice { defineBinding (Literal topic) { setBindingPattern (Binding(topic).addTypeGuard()); + ////////////////////////////////////////////////////////////////////////////TODO: conceptual mismatch here! we don't have an "old entry", because we ourselves are the entry ;-) publishRequestBindingChange(); } }; diff --git a/src/lib/advice/advice.cpp b/src/lib/advice/advice.cpp index 0c0104e2e..ba55fb30f 100644 --- a/src/lib/advice/advice.cpp +++ b/src/lib/advice/advice.cpp @@ -23,14 +23,51 @@ #include "lib/advice.hpp" #include "lib/advice/index.hpp" +#include "lib/singleton.hpp" +#include "include/logging.h" +#include + +using lib::Singleton; namespace lib { namespace advice { // LUMIERA_ERROR_DEFINE (MISSING_INSTANCE, "Existing ID registration without associated instance"); + + namespace { // ======= implementation of the AdviceSystem ============ + + class AdviceSystem + : public Index + , boost::noncopyable + { + + public: + AdviceSystem() + { + INFO (library, "Initialising Advice Index tables."); + } + + ~AdviceSystem() + { + INFO (library, "Shutting down Advice system."); + } + }; + + + /** hidden implementation-level access to the AdviceSystem */ + Singleton aSys; + + + } //(End) AdviceSystem implementation + + + + /* ====== AdviceLink : access point for Provisions and Requests ====== */ + + /** allocate raw storage for a buffer holding the actual piece of advice. We need to manage this internally, as the original advice::Provision may go out of scope, while the advice information as such remains valid. @@ -45,30 +82,49 @@ namespace advice { } + /** when the Provision actually sets advice data, this is copied + * into an internal buffer within the AdviceSystem. We then use the + * Index to remember the presence of this advice data and to detect + * possible matches with existing advice::Request entries. + * @param adviceData pointer to the copied data, + * actually pointing to an ActiveProvision + */ void - AdviceLink::publishProvision (PointOfAdvice*) + AdviceLink::publishProvision (PointOfAdvice* newProvision) { - UNIMPLEMENTED ("change advice provision registration"); + const PointOfAdvice* previousProvision (getSolution (*this)); + setSolution (this, newProvision); + + if (!previousProvision && newProvision) + aSys().addProvision (*newProvision); + else + if (previousProvision && newProvision) + aSys().modifyProvision (*previousProvision, *newProvision); + else + if (previousProvision && !newProvision) + aSys().removeProvision (*previousProvision); ////////////////////////////TODO: don't we need to release buffer storage here? } + /** when advice is retracted explicitly, + * after removing the provision index entry + * we also need to re-process any requests + * which happen to match our binding... + */ void AdviceLink::discardSolutions () { - UNIMPLEMENTED ("notify index of retracted advice"); + const PointOfAdvice* existingProvision (getSolution (*this)); + setSolution (this, NULL ); + if (existingProvision) + aSys().removeProvision (*existingProvision); ////////////////////////////TODO: don't we need to release buffer storage here? } - void - AdviceLink::publishBindingChange () - { - UNIMPLEMENTED ("propagate binding change to index"); - } - - void AdviceLink::publishRequestBindingChange() { + ////////////////////////////////////////////////////////////////////////////TODO: conceptual mismatch here! we don't have an "old entry", because we ourselves are the entry ;-) UNIMPLEMENTED ("propagate binding change to index"); } @@ -76,14 +132,14 @@ namespace advice { void AdviceLink::registerRequest() { - UNIMPLEMENTED ("registrate request with the index"); + aSys().addRequest (*this); } void AdviceLink::deregisterRequest() { - UNIMPLEMENTED ("detach request from index"); + aSys().removeRequest (*this); } diff --git a/src/lib/advice/index.hpp b/src/lib/advice/index.hpp index e15c308d0..0fa0f9201 100644 --- a/src/lib/advice/index.hpp +++ b/src/lib/advice/index.hpp @@ -350,7 +350,9 @@ namespace advice { requestEntries_[nKey].append (newEntry); } else - requestEntries_[nKey].overwrite (oldRef, newEntry); + { + requestEntries_[nKey].overwrite (oldRef, newEntry); + } provisionEntries_[nKey].publish_latest_solution (newEntry); }