Free Electron
RecordArrayAV.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_RecordArrayAV_h__
8 #define __data_RecordArrayAV_h__
9 
10 namespace fe
11 {
12 
13 struct hash_av
14 { FE_UWORD operator()(const FE_UWORD &u) const
15  { return u; } };
16 
17 struct eq_av
18 { bool operator()(FE_UWORD u1, FE_UWORD u2) const
19  { return u1 == u2; } };
20 
21 typedef HashMap<FE_UWORD, IWORD, hash_av, eq_av> t_av_map;
22 
23 /** @brief Homogeneous collection of Records
24 
25  @ingroup data
26 
27  An array of Records, or more precisely an array of state block pointers
28  all pointing to state blocks of the same layout. Therefore only a single
29  reference to the layout itself is stored. Therefore this record array
30  object consumes less memory than an array of record objects.
31  */
32 class FE_DL_EXPORT RecordArrayAV : public Counted
33 {
34  public:
35  RecordArrayAV(void);
36  RecordArrayAV(sp<LayoutAV> spLayout);
37  RecordArrayAV(sp<LayoutAV> spLayout, FE_UWORD aCount);
38  RecordArrayAV(const RecordArrayAV &other);
39 virtual ~RecordArrayAV(void);
40 
41  RecordArrayAV &operator=(const RecordArrayAV &other);
42  FE_UWORD idr(IWORD index);
43  /** Return the length of the array. */
44  IWORD length(void);
45  /** Return the Layout. */
46  sp<Layout> layout(void);
47  /** Return a raw pointer to the Layout. Mainly intended for Accessor
48  for speed. */
49  Layout *rawLayout(void) const;
50  /** Add the given record to the array. If the record array already
51  has records and the Layout is different than for @em record
52  the record will not be added and false will be returned.
53  On success true is returned and if @em index is not NULL the index
54  of the added record is return in @em index. */
55  bool add(const RecordAV &record, IWORD *index = NULL);
56  bool add(sp<RecordArrayAV> spRA, IWORD start, IWORD size);
57 
58  /** @internal
59  Add records without triggering watchers. */
60  bool addCovert(const RecordAV &record, IWORD *index = NULL);
61  /** @internal
62  Add records without triggering watchers. */
63  bool addCovert(sp<RecordArrayAV> spRA,
64  IWORD start, IWORD size);
65 
66  /** create and add a record of an already set Layout. This avoids
67  the overhead of checking for duplicates. */
68  bool addCreateCovert(U32 a_count);
69 
70  /** Remove the given record from the array. On success return
71  true and if @em index is provided return the index of the removed
72  record. If the record is not in the array return false. */
73  bool remove(const RecordAV &record, IWORD *index = NULL);
74 
75  /** Remove record at given index. The array is kept
76  contiguous by moving the last element into the
77  the given index after removal. Therefore, in
78  an iteration that involves deletion it is best
79  to iterate backwards through the array. */
80  void remove(IWORD index);
81 
82  /** @internal
83  Remove records without triggering watchers. */
84  bool removeCovert(const RecordAV &record,IWORD *index=NULL);
85  /** @internal
86  Remove records without triggering watchers. */
87  void removeCovert(IWORD index);
88  /// @internal
89  void bind(sp<RecordGroup> a_spRecordGroup)
90  { m_hpRecordGroup=a_spRecordGroup; }
91 
92  /** Return the record at the given index. */
93  RecordAV getRecord(IWORD index);
94  /// Return a non-persistent record for the given index
95  WeakRecordAV getWeakRecord(IWORD index);
96  /** Clear the record array. */
97  void clear(void);
98  /** Return true if @em record is in the record array. Otherwise return
99  false. */
100  bool find(const RecordAV &record);
101 
102  void set(WeakRecordAV &record, IWORD index);
103  void set(RecordAV &record, IWORD index);
104 
105  void setLayout(const sp<LayoutAV>& rspLayout);
106 
107  /// @brief Remove any invalid weak references
108  void prune(void);
109 
110  /** @internal
111 
112  @brief Choose weak referencing
113 
114  This should only be set by RecordGroup at
115  construction. */
116  void setWeak(BWORD weak);
117 
118  /// @brief Return TRUE if using weak referencing
119  BWORD isWeak(void) const { return m_weak; }
120 
121  /** @internal
122 
123  @brief Don't retain a mappping from Record
124  to array index.
125 
126  RecordArray::remove will be faster,
127  while RecordArray::find will be slower.
128 
129  This should only be set by RecordGroup at
130  construction. */
131  void enableDuplicates(bool a_bool);
132 
133  /** @internal
134 
135  @brief Don't reorder entries during removal.
136 
137  RecordArray::remove can be slower,
138  particularly if enableDuplicates is false.
139 
140  This should only be set by RecordGroup at
141  construction. */
142  void maintainOrder(bool a_bool);
143 
144 
145  template <class T>
146  T &accessAttribute(FE_UWORD aLocator,
147  FE_UWORD aIndex) const;
148  private:
149  /** Return the arrayindex at the given index. */
150  FE_UWORD arrayindex(IWORD index) const;
151  template <class T>
152  T &accessAttributeUnsafe(FE_UWORD aLocator,
153  FE_UWORD aIndex) const;
154  private:
155  void grow(void);
156  void copy(const RecordArrayAV &other);
157 
158  I32 readSerialNumber(IWORD index) const;
159 
160  void trackBlock(U32 index);
161  void untrackBlock(U32 index);
162 
163  void acquireAV(IWORD index);
164  void releaseAV(IWORD index);
165 
166  private:
167  hp<RecordGroup> m_hpRecordGroup;
168  sp<LayoutAV> m_spLayout;
169  Array<FE_UWORD> m_pArrayIndex;
170  Array<IWORD> m_pSN;
171  BWORD m_weak;
172  FE_UWORD m_serialLocator;
173  bool m_duplicates;
174  bool m_maintainOrder;
175  t_av_map m_av_map;
176 
177 #if FE_COUNTED_TRACK
178  public:
179 const String& name(void) const
180  { return m_spLayout.isValid()?
181  m_spLayout->name(): Counted::name(); }
182 const String verboseName(void) const
183  { return "RecordArray " +
184  String(m_weak? "(weak) ": "") + name(); }
185 #endif
186 };
187 
188 template <class T>
189 inline T &RecordArrayAV::accessAttribute(FE_UWORD aLocator, FE_UWORD aIndex) const
190 {
191 // return *(T *)(m_spLayout
192 // ->m_attributeVector[m_spLayout->m_locatorTable[aLocator]]
193 // ->raw_at(arrayindex(aIndex)));
194 #if 0
195  return *(T *)(m_spLayout
196  ->m_attributeVector[m_spLayout->m_locatorTable[aLocator]]
197  ->raw_at(m_pArrayIndex[aIndex]));
198 #endif
199  return *(T *)(m_spLayout->voidAccess(aLocator, m_pArrayIndex[aIndex]));
200 }
201 
202 template <class T>
203 inline T &RecordArrayAV::accessAttributeUnsafe(
204  FE_UWORD aLocator, FE_UWORD aIndex) const
205 {
206 #if 0
207  return *(T *)(m_spLayout
208  ->m_attributeVector[m_spLayout->m_locatorTable[aLocator]]
209  ->raw_at(m_pArrayIndex[aIndex]));
210 #endif
211  return *(T *)(m_spLayout->voidAccess(aLocator, m_pArrayIndex[aIndex]));
212 }
213 
214 
215 class PtrRecordArrayAVInfo : public BaseType::Info
216 {
217  public:
218 virtual IWORD output(std::ostream &ostrm, void *instance, t_serialMode mode);
219 virtual void input(std::istream &istrm, void *instance, t_serialMode mode);
220 virtual IWORD iosize(void);
221 virtual bool getConstruct(void);
222 virtual void construct(void *instance);
223 virtual void destruct(void *instance);
224 };
225 
226 inline void RecordArrayAV::setWeak(BWORD weak)
227 {
228  m_weak = weak;
229 #if FE_COUNTED_TRACK
230  //* propagate name change
231  sp<RecordArrayAV> spRA(this);
232 #endif
233 }
234 
235 inline void RecordArrayAV::maintainOrder(BWORD a_bool)
236 {
237  m_maintainOrder = a_bool;
238 }
239 
240 inline void RecordArrayAV::set(WeakRecordAV &record, IWORD index)
241 {
242  record.set(m_pArrayIndex[index], m_spLayout);
243 }
244 
245 inline void RecordArrayAV::set(RecordAV &record, IWORD index)
246 {
247  record.set(m_pArrayIndex[index], m_spLayout);
248 }
249 
250 inline IWORD RecordArrayAV::length(void)
251 {
252  return m_pArrayIndex.size();
253 }
254 
255 // TODO: AJW: if we choose just AV,
256 // go back to returning const reference of LayoutAV
258 {
259  return m_spLayout;
260 }
261 
263 {
264  RecordAV record;
265  FE_UWORD ai=arrayindex(index);
266  if(ai != LayoutAV::arrayindexNone)
267  {
268  record.set(ai, m_spLayout);
269  }
270  return record;
271 }
272 
274 {
275  WeakRecordAV record;
276  FE_UWORD ai=arrayindex(index);
277  if(ai != LayoutAV::arrayindexNone)
278  {
279  record.set(ai, m_spLayout);
280  }
281  return record;
282 }
283 
284 inline void RecordArrayAV::acquireAV(IWORD index)
285 {
286  if(!m_weak)
287  {
288  m_spLayout->acquireArrayIndex(arrayindex(index));
289  }
290  trackBlock(index);
291 }
292 
293 inline void RecordArrayAV::releaseAV(IWORD index)
294 {
295  untrackBlock(index);
296  if(!m_weak)
297  {
298  m_spLayout->releaseArrayIndex(arrayindex(index));
299  }
300 }
301 
302 inline I32 RecordArrayAV::readSerialNumber(IWORD index) const
303 {
304  if(m_serialLocator!=LayoutAV::locatorNone &&
305  m_pArrayIndex[index]!=LayoutAV::arrayindexNone)
306  {
307 #ifdef FE_AV_FASTITER_ENABLE
308  if(!m_spLayout->existenceCheck(m_serialLocator, m_pArrayIndex[index]))
309  {
310  return -1;
311  }
312 #endif
313  return accessAttributeUnsafe<int>(m_serialLocator, index);
314  }
315  else
316  {
317  return -1;
318  }
319 }
320 
321 
322 inline FE_UWORD RecordArrayAV::idr(IWORD index)
323 {
324  return m_spLayout->idr(arrayindex(index));
325 }
326 
327 inline void RecordArrayAV::untrackBlock(U32 index)
328 {
329 #if FE_COUNTED_TRACK
330 // untrackReference(this, this);
331 #endif
332 }
333 
334 inline void RecordArrayAV::trackBlock(U32 index)
335 {
336 #if FE_COUNTED_TRACK
337  //* NO GOOD
338 // trackReference(this,this,"RecordArray");
339 #endif
340 }
341 
342 
343 inline FE_UWORD RecordArrayAV::arrayindex(IWORD index) const
344 {
345 #if FE_CODEGEN<=FE_DEBUG
346  if(index<0 || index >= IWORD(m_pArrayIndex.size()))
347  {
348  feX("fe::RecordArray::data","index out of range");
349  }
350 #endif
351  if(m_weak && m_pSN[index]>=0 && m_pSN[index]!=readSerialNumber(index))
352  {
353  feLog("RecordArray::data weak element %d is not valid (%d vs %d)\n",
354  index,m_pSN[index],readSerialNumber(index));
355 #if FE_COUNTED_TRACK
356  feLog(" name \"%s\"\n",name().c_str());
357 #endif
358 
359  *(const_cast<FE_UWORD *>(&(m_pArrayIndex[index])))=
360  LayoutAV::arrayindexNone;
361  return LayoutAV::arrayindexNone;
362  }
363  return m_pArrayIndex[index];
364 }
365 
366 };
367 
368 #endif /* __data_RecordArrayAV_h__ */
369 
Homogeneous collection of Records.
Definition: RecordArrayAV.h:32
WeakRecordAV getWeakRecord(IWORD index)
Return a non-persistent record for the given index.
Definition: RecordArrayAV.h:273
Heap-based support for classes participating in fe::ptr <>
Definition: Counted.h:35
kernel
Definition: namespace.dox:3
void setWeak(BWORD weak)
Choose weak referencing.
Definition: RecordArrayAV.h:226
IWORD length(void)
Return the length of the array.
Definition: RecordArrayAV.h:250
RecordAV getRecord(IWORD index)
Return the record at the given index.
Definition: RecordArrayAV.h:262
Automatically reference-counted string container.
Definition: String.h:128
BWORD isWeak(void) const
Return TRUE if using weak referencing.
Definition: RecordArrayAV.h:119
FE_UWORD arrayindex(IWORD index) const
Return the arrayindex at the given index.
Definition: RecordArrayAV.h:343
Reference to an instance of a Layout.
Definition: RecordAV.h:25
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53
Non-persistent reference to an instance of a Layout.
Definition: WeakRecordAV.h:17
sp< Layout > layout(void)
Return the Layout.
Definition: RecordArrayAV.h:257
void bind(sp< RecordGroup > a_spRecordGroup)
Definition: RecordArrayAV.h:89
void maintainOrder(bool a_bool)
Don&#39;t reorder entries during removal.
Definition: RecordArrayAV.h:235