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:
void publishProvision (PointOfAdvice*);
void discardSolutions ();
void publishBindingChange();
void publishRequestBindingChange();
void registerRequest();
@ -240,11 +239,12 @@ namespace advice {
defineBinding (Literal topic)
{
setBindingPattern (Binding(topic).addTypeGuard<AD>());
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<class AD>
PointOfAdvice*
inline PointOfAdvice*
Provision<AD>::storeCopy (AD const& advice_given)
{
typedef ActiveProvision<AD> Holder;
return new(getBuffer(sizeof(Holder))) Holder (*this, advice_given);
}
{
typedef ActiveProvision<AD> 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<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)
{
setBindingPattern (Binding(topic).addTypeGuard<AD>());
////////////////////////////////////////////////////////////////////////////TODO: conceptual mismatch here! we don't have an "old entry", because we ourselves are the entry ;-)
publishRequestBindingChange();
}
};

View file

@ -23,14 +23,51 @@
#include "lib/advice.hpp"
#include "lib/advice/index.hpp"
#include "lib/singleton.hpp"
#include "include/logging.h"
#include <boost/noncopyable.hpp>
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<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.
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<AD>
*/
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);
}

View file

@ -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);
}