86 #ifndef LUMIERA_ADVICE_INDEX_H 87 #define LUMIERA_ADVICE_INDEX_H 99 #include <boost/operators.hpp> 100 #include <unordered_map> 108 using std::placeholders::_1;
109 using std::unordered_map;
155 : pair<Binding::Matcher, POA*>
156 , boost::equality_comparable<Entry, POA,
157 boost::equality_comparable<Entry>
162 : pair<Binding::Matcher, POA*> (elm.getMatcher(), &elm)
168 operator string() const
170 return "E-" +hash_value(this->first) +
"--> "+ this->second ;
176 return a.second == b.second;
180 operator== (
Entry const& a, POA
const& p)
182 return a.second == &p;
187 typedef vector<Entry> EntryList;
188 typedef typename EntryList::iterator EIter;
204 REQUIRE (!contains (elm),
"Duplicate entry");
205 try { elms_.push_back (
Entry(elm)); }
207 catch(std::bad_alloc&)
209 throw error::Fatal(
"AdviceSystem failure due to exhausted memory");
214 overwrite (POA
const& oldRef, POA& newElm)
216 EIter pos = std::find (elms_.begin(),elms_.end(), oldRef);
217 REQUIRE (pos!=elms_.end(),
"Attempt to overwrite an entry which isn't there.");
218 REQUIRE_IF (&oldRef != &newElm, !contains (newElm),
"Duplicate entry");
220 *pos =
Entry(newElm);
222 REQUIRE_IF (&oldRef != &newElm, !contains (oldRef),
"Duplicate entry");
226 remove (POA
const& refElm)
228 EIter pos = std::find (elms_.begin(),elms_.end(), refElm);
229 if (pos!=elms_.end())
232 ENSURE (!contains (refElm),
"Duplicate entry");
236 contains (POA
const& refElm)
238 for (EIter i=elms_.begin(); i!=elms_.end(); ++i)
239 if (*i == refElm)
return true;
243 operator string() const
245 string dump{
"elmList("+toString(elms_.size())+
")\n"};
246 for (
auto const&
entry : elms_)
247 dump +=
"E...:"+
entry+
"\n";
254 return eachElm (elms_);
263 find_latest_solution (POA& requestElm)
265 typedef typename EntryList::reverse_iterator RIter;
267 for (RIter ii=this->elms_.rbegin();
268 ii!=this->elms_.rend();
270 if (ii->first.matches (pattern))
277 publish_latest_solution (POA& requestElm)
279 POA* solution = find_latest_solution (requestElm);
283 requestElm.setSolution (solution);
285 requestElm.setSolution ( NULL );
294 publish_all_solutions (POA& provisionElm)
297 for (EIter ii=this->elms_.begin();
298 ii!=this->elms_.end();
300 if (pattern.matches (ii->first))
303 ii->second->setSolution (&provisionElm);
307 retract_all_solutions (POA
const& oldProv,
ProvisionCluster& possibleReplacementSolutions)
310 for (EIter ii=this->elms_.begin();
311 ii!=this->elms_.end();
313 if (pattern.matches (ii->first))
316 possibleReplacementSolutions.publish_latest_solution (*(ii->second));
320 rewrite_all_solutions (POA
const& oldProv, POA& newProv,
ProvisionCluster& possibleReplacementSolutions)
324 for (EIter ii=this->elms_.begin();
325 ii!=this->elms_.end();
327 if (newPattern.matches (ii->first))
328 ii->second->setSolution (&newProv);
330 if (oldPattern.matches (ii->first))
331 possibleReplacementSolutions.publish_latest_solution (*(ii->second));
339 typedef unordered_map<HashVal, RequestCluster> RTable;
340 typedef unordered_map<HashVal, ProvisionCluster> PTable;
342 mutable RTable requestEntries_;
343 mutable PTable provisionEntries_;
350 addRequest (POA&
entry)
352 HashVal key (hash_value(entry));
353 requestEntries_[key].append (entry);
354 provisionEntries_[key].publish_latest_solution (entry);
366 HashVal nKey (hash_value(entry));
369 requestEntries_[nKey].append (entry);
370 requestEntries_[oKey].remove (entry);
374 requestEntries_[nKey].overwrite (entry, entry);
376 provisionEntries_[nKey].publish_latest_solution (entry);
380 removeRequest (POA
const& refEntry)
382 HashVal oKey (hash_value(refEntry));
383 requestEntries_[oKey].remove (refEntry);
388 addProvision (POA& entry)
390 HashVal key (hash_value(entry));
391 provisionEntries_[key].append (entry);
392 requestEntries_[key].publish_all_solutions (entry);
396 modifyProvision (POA
const& oldRef, POA& newEntry)
398 HashVal oKey (hash_value(oldRef));
399 HashVal nKey (hash_value(newEntry));
402 provisionEntries_[nKey].append (newEntry);
403 provisionEntries_[oKey].remove (oldRef);
404 requestEntries_[nKey].publish_all_solutions (newEntry);
405 requestEntries_[oKey].retract_all_solutions (oldRef, provisionEntries_[oKey]);
409 provisionEntries_[nKey].overwrite (oldRef, newEntry);
410 requestEntries_[nKey].rewrite_all_solutions (oldRef,newEntry, provisionEntries_[nKey]);
415 removeProvision (POA
const& refEntry)
417 HashVal key (hash_value(refEntry));
418 provisionEntries_[key].remove (refEntry);
419 requestEntries_[key].retract_all_solutions (refEntry, provisionEntries_[key]);
430 WARN (library,
"Purging Advice Binding Index...");
431 requestEntries_.clear();
432 provisionEntries_.clear();
445 return request_count() + provision_count();
449 request_count()
const 455 provision_count()
const 461 hasRequest (POA
const& refEntry)
const 463 return requestEntries_[hash_value(refEntry)].contains (refEntry);
467 hasProvision (POA
const& refEntry)
const 469 return provisionEntries_[hash_value(refEntry)].contains (refEntry);
487 void verify_Entry (Entry
const&,
HashVal)
const;
488 void verify_Request (Entry
const&,
HashVal)
const;
512 ,LUMIERA_ERROR_INDEX_CORRUPTED}
530 typedef typename RTable::const_iterator RTIter;
531 typedef typename PTable::const_iterator PTIter;
534 for (PTIter ii =provisionEntries_.begin();
535 ii != provisionEntries_.end(); ++ii)
538 Cluster& clu = unConst(ii->second);
539 for_each (clu.allElms(), &Index::verify_Entry,
this, _1, hash);
541 for (RTIter ii=requestEntries_.begin();
542 ii != requestEntries_.end(); ++ii)
545 Cluster& clu = unConst(ii->second);
546 for_each (clu.allElms(), &Index::verify_Request,
this, _1, hash);
551 catch(SelfCheckFailure& failure)
554 ERROR (library,
"%s", failure.what());
561 #define VERIFY(_CHECK_, DESCRIPTION) \ 563 throw SelfCheckFailure ((DESCRIPTION)); 570 VERIFY (hash == hash_value(e.first),
"Wrong bucket, hash doesn't match bucket");
571 VERIFY (e.second,
"Invalid Entry: back-link is NULL");
578 verify_Entry (e,hash);
579 POA& request = *(e.second);
580 const POA* solution (request.getSolution());
581 if (solution && hasProvision(*solution))
583 POA* currentSolution = provisionEntries_[hash].find_latest_solution (request);
584 VERIFY (e.first.matches (solution->getMatcher()),
"stored advice solution not supported by binding match");
585 VERIFY (
bool(currentSolution),
"unable to reproduce stored solution with the current provisions")
586 VERIFY (solution == currentSolution,
"stored advice solution isn't the topmost solution for this request")
Functor object for matching against another Binding.
AnyPair entry(Query< TY > const &query, typename WrapReturn< TY >::Wrapper &obj)
helper to simplify creating mock table entries, wrapped correctly
inline string literal This is a marker type to indicate that
This header is for including and configuring NoBug.
static size_t sumClusters(IT ii)
internal: sum element count over all clusters in the given hashtable
Derived specific exceptions within Lumiera's exception hierarchy.
A pattern to define and identify a specific attachment to the Advice system.
Marker types to indicate a literal string and a Symbol.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
bool isValid() const
validity self-check
lumiera_err lumiera_error(void)
Get and clear current error state.
void for_each(CON const &elements, FUN function, P1 &&bind1, ARGS &&...args)
Accept binding for arbitrary function arguments.
_SeqT< CON >::Range eachElm(CON &coll)
Lumiera error handling (C++ interface).
size_t HashVal
a STL compatible hash value
Lumiera public interface.
void modifyRequest(HashVal oKey, POA &entry)
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
Preconfigured adapters for some STL container standard usage situations.
Index datastructure for organising advice solutions.
Perform operations "for each element" of a collection.
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
_MapIterT< IT >::ValIter eachVal(IT const &begin, IT const &end)
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.