Lumiera  0.pre.03
»edit your freedom«
defs-registry.hpp
Go to the documentation of this file.
1 /*
2  DEFS-REGISTRY.hpp - implementation of the default object store
3 
4  Copyright (C) Lumiera.org
5  2008, 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 
47 #ifndef LUMIERA_QUERY_DEFS_REGISTRY_H
48 #define LUMIERA_QUERY_DEFS_REGISTRY_H
49 
50 
51 #include "lib/p.hpp"
52 #include "lib/util.hpp"
53 #include "lib/util-foreach.hpp"
54 #include "lib/sync-classlock.hpp"
55 #include "lib/format-string.hpp"
56 #include "lib/query-util.hpp"
57 #include "common/query.hpp"
58 #include "lib/nocopy.hpp"
59 
60 #include <set>
61 #include <vector>
62 #include <memory>
63 
64 
65 namespace lumiera{
66 namespace query {
67 
68  using lib::P;
69  using lib::ClassLock;
70  using std::weak_ptr;
71  using std::string;
72 
73  namespace impl {
74 
75  namespace {
76  using util::_Fmt;
77 
78  uint maxSlots (0);
79  _Fmt dumpRecord ("%2i| %64s --> %s\n");
80  }
81 
82 
83  struct TableEntry
84  {
85  virtual ~TableEntry() {};
86  };
87 
90  typedef std::vector< P<TableEntry> > Table;
91 
92 
96  template<class TAR>
97  struct Record
98  {
99  QueryKey queryKey;
100  weak_ptr<TAR> objRef;
101  uint degree;
102 
103  Record (Query<TAR> const& q, P<TAR> const& obj)
104  : queryKey (q)
105  , objRef (obj)
106  , degree(queryKey.degree())
107  { }
108 
109 
110  struct Search
111  {
112  Search (P<TAR> const& obj)
113  : obj_(obj) { }
114 
115  P<TAR> const& obj_;
116 
117  bool
118  operator() (Record const& rec)
119  {
120  P<TAR> storedObj (rec.objRef.lock());
121  return storedObj && (storedObj == obj_);
122  }
123  };
124 
125  friend bool
126  operator< (Record one, Record two)
127  {
128  return one.queryKey < two.queryKey;
129  }
130 
131  operator string () const { return dumpRecord % degree % queryKey.display() % dumpObj(); }
132  string dumpObj () const { P<TAR> o (objRef.lock()); return o? string(*o):"dead"; }
133  };
134 
140  template<class TAR>
141  struct Slot
142  : public TableEntry
143  {
144  typedef std::set<Record<TAR>> Registry;
145 
146  Registry registry;
147  static size_t index;
148 
149  static Registry&
150  access (Table& table)
151  {
152  if ( !index
153  || index > table.size()
154  ||!table[index-1])
155  createSlot (table);
156 
157  ASSERT (0 < index && index<=table.size() && table[index-1]);
158  Slot* item = static_cast<Slot*> (table[index-1].get());
159  return item->registry;
160  }
161 
162  private:
163  static void
164  createSlot (Table& table)
165  {
166  ClassLock<TableEntry> guard;
167  if (!index)
168  index = ++maxSlots;
169  if (index > table.size())
170  table.resize (index);
171  table[index-1].reset(new Slot);
172  }
173  };
174 
175 
176  // static vars to organise one Table Slot per type....
177  template<class TAR>
178  size_t Slot<TAR>::index (0);
179 
180 
181 
182 
197  {
198  Table table_;
199 
200  public:
202  template<class TAR>
203  class Iter
204  {
205  friend class DefsRegistry;
206  typedef typename Slot<TAR>::Registry::iterator II;
207 
208  II p,i,e;
209  P<TAR> next, ptr;
210 
211  Iter (II from, II to)
212  : p(from), i(from), e(to)
213  {
214  if (i!=e) ++i; // p is next to be tested, i always one ahead
215  operator++ ();
216  }
217 
218  Iter (II match, II from, II to)
219  : p(match), i(from), e(to)
220  {
221  operator++ (); // init to first element (or to null if empty)
222  }
223 
224  P<TAR>
225  findNext ()
226  {
227  while (!next)
228  {
229  if (p==e) break;
230  next = p->objRef.lock();
231  p = i++;
232  }
233  return next;
234  }
235 
236 
237  public:
238  P<TAR> operator* () { return ptr; }
239  bool hasNext () { return next || findNext(); }
240  Iter& operator++ ()
241  {
242  ptr=findNext();
243  next.reset();
244  return *this;
245  }
246  };
247 
257  template<class TAR>
258  Iter<TAR>
259  candidates (Query<TAR> const& query)
260  {
261  P<TAR> dummy;
262  Record<TAR> entry (query, dummy);
263  typedef typename Slot<TAR>::Registry Registry;
264  Registry& registry = Slot<TAR>::access(table_);
265 
266  // try to get a possible direct match (same query)
267  typename Registry::iterator pos = registry.find (entry);
268  typename Registry::iterator end = registry.end();
269 
270  if (pos==end)
271  return Iter<TAR> (registry.begin(), end); // just enumerate contents
272  else
273  return Iter<TAR> (pos, registry.begin(), end); // start with direct match
274  }
275 
276 
284  template<class TAR>
285  bool
286  put (P<TAR> const& obj, Query<TAR> const& query)
287  {
288  Record<TAR> entry (query, obj);
289  typedef typename Slot<TAR>::Registry Registry;
290  typedef typename Registry::iterator RIter;
291 
292  Registry& registry = Slot<TAR>::access(table_);
293  RIter pos = registry.lower_bound (entry);
294  if ( pos!=registry.end()
295  && pos->queryKey == query)
296  {
297  P<TAR> storedObj (pos->objRef.lock());
298  if (storedObj)
299  return (storedObj == obj);
300  else
301  // use the opportunity to purge the expired entry
302  registry.erase(pos++);
303  }
304  // no existing entry....
305  registry.insert(pos, entry);
306  ENSURE (registry.find (entry) != registry.end());
307  return true;
308  }
309 
310 
314  template<class TAR>
315  bool
316  forget (P<TAR> const& obj)
317  {
318  typedef typename Slot<TAR>::Registry Registry;
319  typedef typename Record<TAR>::Search SearchFunc;
320 
321  Registry& registry = Slot<TAR>::access(table_);
322  return util::remove_if(registry, SearchFunc (obj));
323  }
324 
325 
329  template<class TAR>
330  string
331  dump ()
332  {
333  string res;
334  util::for_each ( Slot<TAR>::access(table_)
335  , [&] (Record<TAR>& entry)
336  {
337  res += string(entry);
338  }
339  );
340  return res;
341  }
342  };
343 
344 
345 
346  } // (End) impl namespace
347 
348  using impl::DefsRegistry;
349 
350 
351 }} // namespace lumiera::query
352 #endif
used for enumerating solutions
static size_t index
where to find this Slot in every Table
Utilities to support working with predicate queries.
Basic and generic representation of an internal query.
AnyPair entry(Query< TY > const &query, typename WrapReturn< TY >::Wrapper &obj)
helper to simplify creating mock table entries, wrapped correctly
< Functor searching for a specific object
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
Front-end for printf-style string template interpolation.
Customised refcounting smart pointer.
A front-end for using printf-style formatting.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
holding a single "default object" entry
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
every new kind of object (Type) creates a new slot in the main Table holding all registered default o...
A special implementation of lib::Sync, where the storage of the object monitor is associated directly...
Iter< TAR > candidates(Query< TAR > const &query)
find a sequence of "default" objects possibly matching the query.
Wrapper for indexing and ordering.
Definition: query.hpp:397
A synchronisation protection guard employing a lock scoped to the parameter type as a whole...
ExampleStrategy::Qualifier two(string additionalArg)
definition of another qualifier two(arg), accepting an additional argument
Lumiera public interface.
Definition: advice.cpp:113
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition: trait.hpp:80
uint maxSlots(0)
number of different registered Types
string dump()
helper for diagnostics.
bool forget(P< TAR > const &obj)
if this object is registered as "default" in some way, drop the registration.
ExampleStrategy::Qualifier one()
definition of a qualifier one()
std::vector< P< TableEntry > > Table
we maintain an independent defaults registry for every participating kind of object.
Perform operations "for each element" of a collection.
Generic interface to express a query for specifically typed result elements exposing some capabilitie...
Definition: query.hpp:279
bool put(P< TAR > const &obj, Query< TAR > const &query)
register the object as being "default" when searching something similar as designated by the given qu...