Free Electron
RecordGroup.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __data_RecordGroup_h__
8 #define __data_RecordGroup_h__
9 
10 namespace fe
11 {
12 
13 class RecordOperation;
14 
15 //* NOTE the watcher functionality should be moved to a Watchable class
16 //* in case it ever gets used for any purpose other that RecordMap
17 
18 //typedef AutoHashMap< hp<Layout>, sp<RecordArray> > t_layout_ra;
19 typedef std::map< hp<Layout>, sp<RecordArray> > t_layout_ra;
20 
21 typedef std::map< BaseAccessor,
22  sp<WatcherI> > t_attribute_watcher;
23 
24 typedef std::set< sp<WatcherI> > t_watchers;
25 
26 /** @brief A heterogenous collection of records.
27 
28  @ingroup data
29 
30  From a membership management point of view this is a
31  collection of Records.
32  From an iteration point of view this is a collection of RecordArrays.
33  Each of these RecordArrays contains Records of a single Layout.
34  */
35 class FE_DL_EXPORT RecordGroup :
36  public Handled<RecordGroup>,
37  public ClassSafe<RecordGroup>
38 {
39  public:
40  RecordGroup(void);
41  RecordGroup(const RecordGroup &other);
42 virtual ~RecordGroup(void) {}
43 
44 virtual RecordGroup &operator=(const RecordGroup &other);
45 
46  /** Add @em record to the collection. */
47 virtual void add(const Record &record);
48  /** Add @em records to the collection. */
49 virtual void add(sp<RecordArray> &records);
50  /** Add @em records to the collection. */
51 virtual void add(sp<RecordGroup> &records);
52  /** @brief Remove @em record from the collection
53 
54  Returns false if record was not present. */
55 virtual bool remove(const Record &record);
56  /** Remove @em records from the collection. */
57 virtual void remove(sp<RecordGroup> &records);
58  /** Clear the collection. */
59 virtual void clear(void);
60  /** Return the number of RecordArray (Layouts). */
61 virtual FE_UWORD size(void);
62  /** Return the the total count of records. */
63 virtual FE_UWORD count(void);
64 
65  /** Return the scope of the first RecordArray within. */
66 virtual sp<Scope> getFirstScope(void);
67 virtual sp<Scope> scope(void);
68 
69  class Info
70  {
71  public:
72  std::set< sp<RecordGroup> > m_rgs;
73  std::set<Record> m_rs;
74  };
75 
76  /** Don't retain a mappping from Record to array index.
77  RecordArray::remove is faster, while RecordArray::find is slower.
78  */
79  void enableDuplicates(bool a_bool);
80 
81  /** Try not to reorder entries in each array.
82 
83  Consider also using enableDuplicates(true).
84  RecordArray::remove can be slower otherwise.
85  */
86  void maintainOrder(bool a_bool);
87 
88  /** Remove all references to the given record with contained records. */
89 virtual void removeReferences(const Record &record,
90  bool recurse=false, Info *info=NULL);
91 
92  /** Perform the RecordOperation @em op on all records. */
93 virtual void all(RecordOperation &op);
94 
95  /** Return true if @em record is in the record group. Otherwise return
96  false. */
97 virtual bool find(const Record &record);
98 
99 virtual sp<RecordArray> getArray(sp<Layout> l_query);
100 virtual sp<RecordArray> getArray(const String layout);
101 
102  template <class T>
103  sp< RecordMap<T> > lookupMap(Accessor<T> accessor);
104  template <class T>
105  Record lookup(Accessor<T> accessor, const T &value);
106 
107  /** @brief Choose weak referencing
108 
109  Usually, this should only occur immediately
110  after construction before any Records are added.
111 
112  Changing this value with existing records
113  incurs the overhead of rebuilding all the
114  underlying arrays. */
115  void setWeak(BWORD weak);
116 
117  /// @brief Return TRUE if using weak referencing
118  BWORD isWeak(void) const { return m_weak; }
119 
120  /// @brief Remove any invalid weak references
121  void prune(void);
122 
123  /** STL style iterator. */
124  class FE_DL_EXPORT iterator
125  {
126  public:
127  friend class RecordGroup;
128 
129  iterator(void) {}
130  iterator(const iterator& it);
131  sp<RecordArray> &operator*(void);
132  sp<RecordArray> *operator->(void);
133  iterator operator++();
134  iterator operator++(int);
135  bool operator==(const iterator &other);
136  bool operator!=(const iterator &other);
137  sp<RecordGroup> group(void);
138  bool check(void);
139  private:
140  t_layout_ra::iterator m_raMapIt;
141  sp<RecordGroup> m_spRG; // be sure to keep RG alive
142  Array<BaseAccessor> m_filters;
143  t_layout_ra::iterator m_endIt;
144  };
145 
146  iterator begin(void);
147  iterator begin(Array<BaseAccessor> filters);
148  iterator end(void);
149 
150  /// @internal
151  void watcherAdd(const Record &record);
152  /// @internal
153  void watcherRemove(const Record &record);
154 
155  private:
156 virtual void removeReferencesFromRecord(Record &from,
157  const Record &record,
158  bool recurse=false, Info *info=NULL);
159  void rebuildArrays(void);
160 
161  t_layout_ra m_raMap;
162  t_attribute_watcher m_indices;
163  t_watchers m_watchers;
164  BWORD m_weak;
165  BWORD m_locking;
166  bool m_duplicates;
167  bool m_maintainOrder;
168 
169 #if FE_COUNTED_TRACK
170  public:
171 const String verboseName(void) const
172  { return "RecordGroup " +
173  String(m_weak? "(weak) ": "") + name(); }
174 #endif
175 };
176 
177 class FE_DL_EXPORT PtrRecordGroupInfo : public BaseType::Info
178 {
179  public:
180 virtual String print(void *instance);
181 virtual IWORD output(std::ostream &ostrm, void *instance, t_serialMode mode);
182 virtual void input(std::istream &istrm, void *instance, t_serialMode mode);
183 virtual IWORD iosize(void);
184 virtual bool getConstruct(void);
185 virtual void construct(void *instance);
186 virtual void destruct(void *instance);
187 };
188 
189 template <class T>
190 sp< RecordMap<T> > RecordGroup::lookupMap(Accessor<T> accessor)
191 {
192  sp< RecordMap<T> > spRI;
193 
194  t_attribute_watcher::iterator it = m_indices.find(accessor);
195  if(it == m_indices.end())
196  {
197  spRI = new RecordMap<T>(accessor);
198  m_indices[accessor] = spRI;
199  m_watchers.insert(spRI);
200  // scan existing records
201  for(RecordGroup::iterator rg_it = this->begin();
202  rg_it != this->end(); rg_it++)
203  {
204  sp<RecordArray> spRA = *rg_it;
205  if(accessor.check(spRA))
206  {
207  for(int i = 0; i < spRA->length(); i++)
208  {
209  spRI->add(spRA->getRecord(i));
210  }
211  }
212  }
213  }
214  else
215  {
216  spRI = it->second;
217  }
218 
219  return spRI;
220 }
221 
222 template <class T>
223 Record RecordGroup::lookup(Accessor<T> accessor, const T &value)
224 {
225  sp< RecordMap<T> > spMap=lookupMap<T>(accessor);
226  FEASSERT(spMap.isValid());
227 
228  return spMap.isValid()? spMap->lookup(value): Record();
229 }
230 
231 inline RecordGroup::RecordGroup(void)
232 {
233  m_weak = FALSE;
234  m_locking = FALSE;
235  m_duplicates = FALSE;
236  m_maintainOrder = FALSE;
237 }
238 
239 inline RecordGroup::RecordGroup(const RecordGroup &other):
240  Castable(),
243 {
244  m_raMap = other.m_raMap;
245  m_weak = other.m_weak;
246  m_locking = other.m_locking;
247  m_duplicates = other.m_duplicates;
248  m_maintainOrder = other.m_maintainOrder;
249 }
250 
251 inline RecordGroup &RecordGroup::operator=(const RecordGroup &other)
252 {
253  SAFEGUARDCLASS;
254  feX("RecordGroup", "uncertain about desired assignment semantics");
255  if(this != &other)
256  {
257  m_raMap = other.m_raMap;
258  m_weak = other.m_weak;
259  m_locking = other.m_locking;
260  m_duplicates = other.m_duplicates;
261  m_maintainOrder = other.m_maintainOrder;
262  }
263  return *this;
264 }
265 
266 inline void RecordGroup::setWeak(BWORD weak)
267 {
268  if(m_weak!=weak)
269  {
270  m_weak = weak;
271  rebuildArrays();
272  }
273 }
274 
275 inline void RecordGroup::enableDuplicates(bool a_bool)
276 {
277  if(m_duplicates!=a_bool)
278  {
279  m_duplicates = a_bool;
280  rebuildArrays();
281  }
282 }
283 
284 inline void RecordGroup::maintainOrder(bool a_bool)
285 {
286  if(m_maintainOrder!=a_bool)
287  {
288  m_maintainOrder = a_bool;
289  rebuildArrays();
290  }
291 }
292 
293 inline FE_UWORD RecordGroup::size(void)
294 {
295  SAFEGUARDCLASS_IF(m_locking);
296  return m_raMap.size();
297 }
298 
299 inline bool RecordGroup::find(const Record &record)
300 {
301  SAFEGUARDCLASS_IF(m_locking);
302  sp<RecordArray> spRA;
303  t_layout_ra::iterator it = m_raMap.find(record.layout());
304  if(it == m_raMap.end())
305  {
306  return false;
307  }
308  return it->second->find(record);
309 }
310 
311 inline void RecordGroup::prune(void)
312 {
313  SAFEGUARDCLASS_IF(m_locking);
314  for(RecordGroup::iterator i_rg = begin(); i_rg != end(); i_rg++)
315  {
316  (*i_rg)->prune();
317  }
318 }
319 
320 inline void RecordGroup::clear(void)
321 {
322  SAFEGUARDCLASS_IF(m_locking);
323  m_raMap.clear();
324 
325  for(t_attribute_watcher::iterator tw_it = m_indices.begin();
326  tw_it != m_indices.end(); tw_it++)
327  {
328  tw_it->second->clear();
329  }
330  for(t_watchers::iterator tw_it = m_watchers.begin();
331  tw_it != m_watchers.end(); tw_it++)
332  {
333  (*tw_it)->clear();
334  }
335 }
336 
337 inline RecordGroup::iterator RecordGroup::begin()
338 {
340  it.m_raMapIt = m_raMap.begin();
341  it.m_endIt = m_raMap.end();
342  it.m_spRG = this;
343  return it;
344 }
345 
346 inline RecordGroup::iterator RecordGroup::end()
347 {
349  it.m_raMapIt = m_raMap.end();
350  it.m_endIt = m_raMap.end();
351  it.m_spRG = this;
352  return it;
353 }
354 
355 inline RecordGroup::iterator::iterator(const RecordGroup::iterator& it)
356 {
357  m_raMapIt=it.m_raMapIt;
358  m_endIt=it.m_endIt;
359  m_spRG=it.m_spRG;
360  m_filters=it.m_filters;
361 }
362 
363 inline sp<RecordArray> &RecordGroup::iterator::operator*(void)
364 {
365  return m_raMapIt->second;
366 }
367 
368 inline sp<RecordArray> *RecordGroup::iterator::operator->(void)
369 {
370  return &(m_raMapIt->second);
371 }
372 
373 inline bool RecordGroup::iterator::check(void)
374 {
375  if(m_raMapIt == m_endIt) { return false; }
376  for(unsigned int i = 0; i < m_filters.size(); i++)
377  {
378  if(!m_filters[i].check(m_raMapIt->second))
379  {
380  return false;
381  }
382  }
383  return true;
384 }
385 inline RecordGroup::iterator RecordGroup::iterator::operator++(void)
386 {
387  do
388  {
389  m_raMapIt++;
390  }
391  while(!check() && m_raMapIt != m_endIt);
392  return *this;
393 }
394 
395 inline RecordGroup::iterator RecordGroup::iterator::operator++(int dummy)
396 {
397  RecordGroup::iterator it = *this;
398  do
399  {
400  m_raMapIt++;
401  }
402  while(!check() && m_raMapIt != m_endIt);
403  return it;
404 }
405 
406 inline bool RecordGroup::iterator::operator==(
407  const RecordGroup::iterator &other)
408 {
409  return (m_raMapIt==other.m_raMapIt);
410 }
411 
412 inline bool RecordGroup::iterator::operator!=(
413  const RecordGroup::iterator &other)
414 {
415  return (m_raMapIt!=other.m_raMapIt);
416 }
417 
418 inline sp<RecordGroup> RecordGroup::iterator::group(void)
419 {
420  return m_spRG;
421 }
422 
423 } /* namespace */
424 
425 #endif /* __data_RecordGroup_h__ */
426 
A heterogenous collection of records.
Definition: RecordGroup.h:35
Class level locking for thread safety.
Definition: Safe.h:213
Base participation non-RTTI fallback dynamic casting mechanism.
Definition: Castable.h:93
kernel
Definition: namespace.dox:3
BWORD isWeak(void) const
Return TRUE if using weak referencing.
Definition: RecordGroup.h:118
The main data access class for the data system.
Definition: Accessor.h:128
virtual FE_UWORD size(void)
Return the number of RecordArray (Layouts).
Definition: RecordGroup.h:293
sp< Layout > layout(void) const
Return the Layout.
Definition: RecordSB.h:189
BWORD operator!=(const DualString &s1, const DualString &s2)
Compare two DualString&#39;s (reverse logic)
Definition: DualString.h:229
virtual bool find(const Record &record)
Return true if record is in the record group.
Definition: RecordGroup.h:299
void enableDuplicates(bool a_bool)
Don&#39;t retain a mappping from Record to array index.
Definition: RecordGroup.h:275
An operation on a record.
Definition: RecordOperation.h:24
BWORD operator==(const DualString &s1, const DualString &s2)
Compare two DualString&#39;s.
Definition: DualString.h:208
Automatically reference-counted string container.
Definition: String.h:128
void setWeak(BWORD weak)
Choose weak referencing.
Definition: RecordGroup.h:266
bool check(const RecordSB &r) const
Return true if record has attribute.
Definition: Accessor.h:314
STL style iterator.
Definition: RecordGroup.h:124
Wrapper for std::vector.
Definition: Array.h:21
virtual void clear(void)
Clear the collection.
Definition: RecordGroup.h:320
Reference to an instance of a Layout.
Definition: RecordSB.h:35
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53
Base class providing an fe::Handle to the derived class.
Definition: Handled.h:209
void maintainOrder(bool a_bool)
Try not to reorder entries in each array.
Definition: RecordGroup.h:284
void prune(void)
Remove any invalid weak references.
Definition: RecordGroup.h:311