Lumiera  0.pre.03
»edit your freedom«
advice.cpp
Go to the documentation of this file.
1 /*
2  Advice - 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 
94 #include "lib/error.hpp"
95 #include "lib/nocopy.hpp"
96 #include "lib/del-stash.hpp"
97 #include "lib/depend.hpp"
98 #include "lib/symbol.hpp"
99 #include "lib/sync.hpp"
100 #include "lib/util.hpp"
101 #include "include/logging.h"
102 #include "common/advice.hpp"
103 #include "common/advice/index.hpp"
104 
105 
106 using lib::Literal;
107 using lib::DelStash;
108 using util::unConst;
109 
110 typedef void (DeleterFunc)(void*);
111 
112 
113 namespace lumiera{
114 namespace advice {
115 
116  namespace { // ======= implementation of the AdviceSystem ============
117 
125  : public lib::Sync<>
127  {
128 
129  DelStash adviceDataRegistry_;
130  Index<PointOfAdvice> index_;
131 
132  public:
133  AdviceSystem()
134  : index_()
135  {
136  TRACE (library, "Initialising Advice Index tables.");
137  }
138 
139  ~AdviceSystem()
140  {
141  TRACE (library, "Shutting down Advice system.");
142  }
143 
144 
145 
146  /* == Advice data storage management == */
147 
155  void*
156  allocateBuffer(size_t siz)
157  {
158  try { return new char[siz]; }
159 
160  catch(std::bad_alloc&)
161  {
162  throw error::Fatal("Unable to store Advice due to memory exhaustion");
163  }
164  ERROR_LOG_AND_IGNORE (memory, "Storing a piece of Advice")
165  throw error::Fatal("Unable to store Advice data");
166  }
167 
168  void
169  releaseBuffer (void* buff, size_t)
170  {
171  delete[] (char*)buff;
172  }
173 
174  void
175  manageAdviceData (PointOfAdvice* entry, DeleterFunc* how_to_delete)
176  {
177  Lock sync{this};
178  adviceDataRegistry_.manage (entry, how_to_delete);
179  }
180 
181  private:
182  void
183  discardEntry (PointOfAdvice* storedProvision)
184  {
185  if (storedProvision)
186  {
187  adviceDataRegistry_.kill (storedProvision);
188  } }
189 
190 
191 
192  public:
193  /* == forward additions and retractions to the index == */
194 
195  void
196  publishRequestBindingChange(PointOfAdvice & req,
197  HashVal previous_bindingKey)
198  {
199  Lock sync{this};
200  index_.modifyRequest(previous_bindingKey, req);
201  }
202 
203  void
204  registerRequest(PointOfAdvice & req)
205  {
206  Lock sync{this};
207  index_.addRequest (req);
208  }
209 
210  void
211  deregisterRequest(PointOfAdvice const& req)
212  {
213  try
214  {
215  Lock sync{this};
216  index_.removeRequest (req);
217  }
218 
219  catch(...)
220  {
221  Literal errID = lumiera_error();
222  WARN (library, "Problems on deregistration of advice request: %s", errID.c());
223  }
224  }
225 
226 
227  void
228  publishProvision (PointOfAdvice* newProvision, const PointOfAdvice* previousProvision)
229  {
230  Lock sync{this};
231 
232  if (!previousProvision && newProvision)
233  index_.addProvision (*newProvision);
234  else
235  if (previousProvision && newProvision)
236  index_.modifyProvision (*previousProvision, *newProvision);
237  else
238  if (previousProvision && !newProvision)
239  index_.removeProvision (*previousProvision);
240 
241  discardEntry (unConst(previousProvision));
242  }
243 
244  void
245  discardSolutions (const PointOfAdvice* existingProvision)
246  {
247  Lock sync{this};
248 
249  if (existingProvision)
250  index_.removeProvision (*existingProvision);
251 
252  discardEntry (unConst(existingProvision));
253  }
254  };
255 
256 
259 
260 
261  } //(End) AdviceSystem implementation
262 
263 
264 
265 
266 
267 
268  /* ====== AdviceLink : access point for Provisions and Requests ====== */
269 
270 
279  void*
281  {
282  return aSys().allocateBuffer(siz);
283  }
284 
285 
286  void
287  AdviceLink::releaseBuffer (void* buff, size_t siz)
288  {
289  aSys().releaseBuffer(buff, siz);
290  }
291 
292 
300  void
301  AdviceLink::manageAdviceData (PointOfAdvice* entry, DeleterFunc* how_to_delete)
302  {
303  aSys().manageAdviceData (entry,how_to_delete);
304  }
305 
306 
307 
308 
321  void
323  {
324  const PointOfAdvice* previousProvision (getSolution());
325  this->setSolution (newProvision);
326 
327  aSys().publishProvision (newProvision, previousProvision);
328  }
329 
330 
339  void
341  {
342  const PointOfAdvice* existingProvision (getSolution());
343  this->setSolution ( NULL );
344  aSys().discardSolutions (existingProvision);
345  }
346 
347 
348  void
349  AdviceLink::publishRequestBindingChange(HashVal previous_bindingKey)
350  {
351  aSys().publishRequestBindingChange (*this, previous_bindingKey);
352  }
353 
354 
355  void
356  AdviceLink::registerRequest()
357  {
358  aSys().registerRequest (*this);
359  }
360 
361 
362  void
363  AdviceLink::deregisterRequest()
364  {
365  aSys().deregisterRequest (*this);
366  }
367 
368 
369 
370 
371 
372 }} // namespace lib::advice
Facility for monitor object based locking.
Definition: sync.hpp:217
the system-wide service to support the implementation of advice collaborations.
Definition: advice.cpp:124
void * allocateBuffer(size_t siz)
low-level allocation of storage to hold advice data
Definition: advice.cpp:156
Basic (abstracted) view of an advice collaboration partner, as used internally by the AdviceSystem to...
Definition: advice.hpp:131
#define ERROR_LOG_AND_IGNORE(_FLAG_, _OP_DESCR_)
convenience shortcut for a sequence of catch blocks just logging and consuming an error...
Definition: error.hpp:275
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
Implementation datastructure for use by the Advice system.
lib::Depend< AdviceSystem > aSys
hidden implementation-level access to the AdviceSystem
Definition: advice.cpp:258
This header is for including and configuring NoBug.
Access point to singletons and other kinds of dependencies designated by type.
Definition: depend.hpp:289
Collecting and finally triggering deleter functions.
Object Monitor based synchronisation.
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.
Expecting Advice and giving Advice: a cross-cutting collaboration of loosely coupled participants...
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
Manage a collection of deleter functions.
Definition: del-stash.hpp:65
Singleton services and Dependency Injection.
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
void modifyRequest(HashVal oKey, POA &entry)
Definition: index.hpp:364
Index datastructure for organising advice solutions.
Definition: index.hpp:150
void discardEntry(PointOfAdvice *storedProvision)
Definition: advice.cpp:183