code up the obvious part of the AdviceSystem implementation

This commit is contained in:
Fischlurch 2010-06-04 04:35:40 +02:00
parent d0e7f9b77d
commit 666d57f6ef
3 changed files with 96 additions and 20 deletions

View file

@ -171,7 +171,6 @@ namespace advice {
protected: protected:
void publishProvision (PointOfAdvice*); void publishProvision (PointOfAdvice*);
void discardSolutions (); void discardSolutions ();
void publishBindingChange();
void publishRequestBindingChange(); void publishRequestBindingChange();
void registerRequest(); void registerRequest();
@ -240,11 +239,12 @@ namespace advice {
defineBinding (Literal topic) defineBinding (Literal topic)
{ {
setBindingPattern (Binding(topic).addTypeGuard<AD>()); setBindingPattern (Binding(topic).addTypeGuard<AD>());
publishBindingChange(); maybe_rePublish();
} }
private: private:
PointOfAdvice* storeCopy (AD const& advice_given); PointOfAdvice* storeCopy (AD const& advice_given);
void maybe_rePublish ();
}; };
@ -289,12 +289,29 @@ namespace advice {
@throw error::External on allocation problems, plus anything @throw error::External on allocation problems, plus anything
the advice data may throw during copy construction. */ the advice data may throw during copy construction. */
template<class AD> template<class AD>
PointOfAdvice* inline PointOfAdvice*
Provision<AD>::storeCopy (AD const& advice_given) Provision<AD>::storeCopy (AD const& advice_given)
{ {
typedef ActiveProvision<AD> Holder; typedef ActiveProvision<AD> Holder;
return new(getBuffer(sizeof(Holder))) Holder (*this, advice_given); 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<class AD>
inline void
Provision<AD>::maybe_rePublish ()
{
typedef const ActiveProvision<AD> AdviceProvision;
AdviceProvision* solution = static_cast<AdviceProvision*> (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) defineBinding (Literal topic)
{ {
setBindingPattern (Binding(topic).addTypeGuard<AD>()); setBindingPattern (Binding(topic).addTypeGuard<AD>());
////////////////////////////////////////////////////////////////////////////TODO: conceptual mismatch here! we don't have an "old entry", because we ourselves are the entry ;-)
publishRequestBindingChange(); publishRequestBindingChange();
} }
}; };

View file

@ -23,13 +23,50 @@
#include "lib/advice.hpp" #include "lib/advice.hpp"
#include "lib/advice/index.hpp" #include "lib/advice/index.hpp"
#include "lib/singleton.hpp"
#include "include/logging.h"
#include <boost/noncopyable.hpp>
using lib::Singleton;
namespace lib { namespace lib {
namespace advice { namespace advice {
// LUMIERA_ERROR_DEFINE (MISSING_INSTANCE, "Existing ID registration without associated instance"); // LUMIERA_ERROR_DEFINE (MISSING_INSTANCE, "Existing ID registration without associated instance");
namespace { // ======= implementation of the AdviceSystem ============
class AdviceSystem
: public Index<PointOfAdvice>
, 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<AdviceSystem> aSys;
} //(End) AdviceSystem implementation
/* ====== AdviceLink : access point for Provisions and Requests ====== */
/** allocate raw storage for a buffer holding the actual piece of advice. /** allocate raw storage for a buffer holding the actual piece of advice.
We need to manage this internally, as the original advice::Provision We need to manage this internally, as the original advice::Provision
@ -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<AD>
*/
void 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 void
AdviceLink::discardSolutions () 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 void
AdviceLink::publishRequestBindingChange() 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"); UNIMPLEMENTED ("propagate binding change to index");
} }
@ -76,14 +132,14 @@ namespace advice {
void void
AdviceLink::registerRequest() AdviceLink::registerRequest()
{ {
UNIMPLEMENTED ("registrate request with the index"); aSys().addRequest (*this);
} }
void void
AdviceLink::deregisterRequest() AdviceLink::deregisterRequest()
{ {
UNIMPLEMENTED ("detach request from index"); aSys().removeRequest (*this);
} }

View file

@ -350,7 +350,9 @@ namespace advice {
requestEntries_[nKey].append (newEntry); requestEntries_[nKey].append (newEntry);
} }
else else
requestEntries_[nKey].overwrite (oldRef, newEntry); {
requestEntries_[nKey].overwrite (oldRef, newEntry);
}
provisionEntries_[nKey].publish_latest_solution (newEntry); provisionEntries_[nKey].publish_latest_solution (newEntry);
} }