Lumiera  0.pre.03
»edit your freedom«
advice.hpp
Go to the documentation of this file.
1 /*
2  ADVICE.hpp - generic loosely coupled interaction guided by symbolic pattern
3 
4  Copyright (C) Lumiera.org
5  2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
98 #ifndef LUMIERA_ADVICE_H
99 #define LUMIERA_ADVICE_H
100 
101 
102 #include "lib/error.hpp"
103 #include "lib/nocopy.hpp"
104 #include "lib/null-value.hpp"
105 #include "lib/symbol.hpp"
106 #include "lib/util.hpp"
107 
108 #include "common/advice/binding.hpp"
109 
110 
111 namespace lumiera{
112 namespace advice {
113 
114  using lib::Literal;
115  using util::isSameObject;
116 
117 
132  {
133  Binding::Matcher pattern_;
134  PointOfAdvice* resolution_;
135 
136  protected:
142  void setBindingPattern (Binding const& binding)
143  {
144  pattern_ = binding.buildMatcher();
145  }
146 
147  public:
148  explicit
149  PointOfAdvice (Binding const& binding)
150  : pattern_(binding.buildMatcher())
151  , resolution_(nullptr)
152  { }
153 
154  // using default copy/assignment
155 
156 
157 
158  /* == Adapter interface for use within the Index == */
159 
160  void
161  setSolution (PointOfAdvice* solution =0)
162  {
163  resolution_ = solution;
164  }
165 
166  const PointOfAdvice*
167  getSolution () const
168  {
169  return resolution_;
170  }
171 
173  getMatcher () const
174  {
175  return pattern_;
176  }
177 
178  friend HashVal
179  hash_value (PointOfAdvice const& entry)
180  {
181  return hash_value (entry.pattern_);
182  }
183  };
184 
185 
186 
187 
195  : public PointOfAdvice
196  {
197  protected:
198  void publishProvision (PointOfAdvice*);
199  void discardSolutions ();
200  void publishRequestBindingChange(HashVal);
201 
202  void registerRequest();
203  void deregisterRequest();
204 
205  static void* getBuffer(size_t);
206  static void releaseBuffer (void*, size_t);
207 
208  typedef void (DeleterFunc)(void*);
209  static void manageAdviceData (PointOfAdvice*, DeleterFunc*);
210 
211  public:
212  explicit
213  AdviceLink (Binding const& binding)
214  : PointOfAdvice(binding)
215  { }
216 
217  // using default copy/assignment
218  };
219 
220 
221 
222 
223 
243  template<class AD>
244  class Provision
245  : protected AdviceLink
246  {
247 
248 
249  /* == policy definitions == */
250 
251  void deregister() { /* NOP */ }
252 
253 
254  public:
255  explicit
256  Provision (Literal bindingSpec =0)
257  : AdviceLink (Binding(bindingSpec).addTypeGuard<AD>())
258  { }
259 
260  ~Provision()
261  {
262  this->deregister();
263  }
264 
265  Provision (Provision const& o)
266  : AdviceLink(o)
267  {
268  setSolution ( NULL );
269  }
270 
271  Provision&
272  operator= (Provision const& o)
273  {
274  if (!isSameObject(*this, o))
275  {
276  AdviceLink::operator= (o);
277  setSolution ( NULL );
278  }
279  return *this;
280  }
281 
282 
283  void setAdvice (AD const& pieceOfAdvice)
284  {
285  publishProvision(
286  storeCopy (pieceOfAdvice));
287  }
288 
289  void retractAdvice()
290  {
291  discardSolutions();
292  }
293 
294  bool
295  isGiven() const
296  {
297  return bool{this->getSolution()};
298  }
299 
300  void
301  defineBinding (Literal topic)
302  {
303  setBindingPattern (Binding(topic).addTypeGuard<AD>());
304  maybe_rePublish();
305  }
306 
307  private:
308  PointOfAdvice* storeCopy (AD const& advice_given);
309  static void releaseAdviceData (void*);
310  void maybe_rePublish ();
311  };
312 
313 
325  template<class AD>
327  : public PointOfAdvice
329  {
330  AD theAdvice_;
331 
332  public:
333  AD const&
334  getAdvice() const
335  {
336  return theAdvice_;
337  }
338 
339  protected:
340  ActiveProvision (PointOfAdvice const& refPoint, AD const& advice_given)
341  : PointOfAdvice(refPoint)
342  , theAdvice_(advice_given)
343  {
344  this->setSolution (this); // not used currently (5/10)
345  }
346 
347  friend class Provision<AD>;
348  };
349 
350 
351  /* ==== memory management for Provision data ===== */
352 
357  template<class AD>
358  inline PointOfAdvice*
359  Provision<AD>::storeCopy (AD const& advice_given)
360  {
361  typedef ActiveProvision<AD> Holder;
362  void* storage = getBuffer(sizeof(Holder));
363  try
364  {
365  Holder* storedProvision = new(storage) Holder (*this, advice_given);
366  manageAdviceData (storedProvision, &releaseAdviceData);
367  return storedProvision;
368  }
369  catch(...)
370  {
371  Literal errID = lumiera_error();
372  releaseBuffer (storage, sizeof(Holder));
373  throw lumiera::error::Fatal ("Failure to store advice data", errID);
374  }
375  }
376 
377 
382  template<class AD>
383  inline void
385  {
386  typedef ActiveProvision<AD> Holder;
387  if (entry)
388  {
389  Holder* obj = static_cast<Holder*> (entry);
390  obj->~Holder();
391  releaseBuffer (entry, sizeof(Holder));
392  }
393  }
394 
395 
400  template<class AD>
401  inline void
403  {
404  typedef const ActiveProvision<AD> AdviceProvision;
405  AdviceProvision* solution = static_cast<AdviceProvision*> (getSolution());
406 
407  if (solution) // create copy of the data holder, using the new binding
408  publishProvision(
409  storeCopy (solution->getAdvice()));
410  }
411 
412 
413 
414 
415 
416 
417 
436  template<class AD>
437  class Request
438  : protected AdviceLink
439  {
440  typedef const ActiveProvision<AD> AdviceProvision;
441 
442 
443  /* == policy definitions == */
444 
445  AD const&
447  {
448  return lib::NullValue<AD>::get();
449  }
450 
451 
452  public:
453  explicit
454  Request (Literal bindingSpec =0)
455  : AdviceLink (Binding(bindingSpec).addTypeGuard<AD>())
456  {
457  registerRequest();
458  }
459 
460  ~Request()
461  {
462  deregisterRequest();
463  }
464 
465  // copying Requests is allowed, using default
466 
467 
468  AD const&
469  getAdvice() const
470  {
471  AdviceProvision* solution = static_cast<AdviceProvision*> (this->getSolution());
472  if (!solution)
473  return this->handleMissingSolution();
474  else
475  return solution->getAdvice();
476  }
477 
478 
483  bool
484  isMatched() const
485  {
486  return bool{this->getSolution()};
487  }
488 
489 
491  void
493  {
494  HashVal previous_bindingKey (hash_value(*this));
495  setBindingPattern (Binding(topic).addTypeGuard<AD>());
496  publishRequestBindingChange (previous_bindingKey);
497  }
498  };
499 
500 
501 
502 
503 
504 }} // namespace lumiera::advice
505 #endif
Access point for the advised entity (client).
Definition: advice.hpp:437
Conjunction of predicates to be matched against a collaboration partner for establishing an Advice co...
Functor object for matching against another Binding.
Basic (abstracted) view of an advice collaboration partner, as used internally by the AdviceSystem to...
Definition: advice.hpp:131
void defineBinding(Literal topic)
set and possibly change the binding term used to retrieve Advice
Definition: advice.hpp:492
Piece of Advice as incorporated into the AdviceSystem.
Definition: advice.hpp:326
static void releaseAdviceData(void *)
Definition: advice.hpp:384
AnyPair entry(Query< TY > const &query, typename WrapReturn< TY >::Wrapper &obj)
helper to simplify creating mock table entries, wrapped correctly
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
Singleton holder for NIL or default value objects.
Definition: null-value.hpp:71
PointOfAdvice * storeCopy(AD const &advice_given)
Definition: advice.hpp:359
bool isMatched() const
Definition: advice.hpp:484
Singleton-style holder for NIL or default values.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Access point for the advising entity (server).
Definition: advice.hpp:244
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...
lumiera_err lumiera_error(void)
Get and clear current error state.
Definition: error-state.c:124
Lumiera error handling (C++ interface).
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:56
Lumiera public interface.
Definition: advice.cpp:113
AD const & handleMissingSolution() const
<
Definition: advice.hpp:446
void setBindingPattern(Binding const &binding)
define or re-define the binding, which specifically labels this attachment to the advice system...
Definition: advice.hpp:142
bool isSameObject(A const &a, B const &b)
compare plain object identity, bypassing any custom comparison operators.
Definition: util.hpp:372