HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_IndexedHashMapT.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_IndexedHashMap.h ( UT Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __UT_IndexedHashMapT__
12 #define __UT_IndexedHashMapT__
13 
14 #include "UT_StringHolder.h"
15 #include "UT_IndexedHashMap.h"
16 
18 
19 /// Convenience class for items which just reference their keys. That is, if
20 /// all the information is available on the key, the item class can be a simple
21 /// key container.
22 ///
23 /// The class has a method that allows for deferred creation given the key
24 /// reference.
25 ///
26 /// @note You will likely want to use ut_IndexedHashMapDeferItemAlloc<KEY,ITEM>
27 /// with this class (since the point of this item class is to allow deferred
28 /// allocation).
29 template <typename KEY>
31 {
32 public:
34  : myKey(&k)
35  {
36  }
38  : myKey(i.myKey)
39  {
40  }
42 
45  {
46  myKey = src.myKey;
47  return *this;
48  }
49 
50  const KEY &getKey() const { return *myKey; }
52  { return *myKey < *i.myKey; }
53 private:
54  const KEY *myKey;
55 };
56 
57 /// A typedef for a string item container. This is an item container which
58 /// holds a UT_IndexedHashMapStringKey
61 
62 /// An allocator object which dis-allows deferred allocation of items
64 {
65 public:
66  /// Return NULL (don't allow deferred construction).
69  {
70  UT_ASSERT(0 && "User must define an allocator for deferred allocation");
71  return NULL;
72  }
73 };
74 
75 /// For ITEM objects which support a deferred constructor (for example, the key
76 /// container item), this can be used as a simple deferred allocator.
77 template <typename KEY, typename ITEM>
79 {
80 public:
81  //// Construct an item when it doesn't already exist in the map
84  {
85  return new ITEM(*(static_cast<const KEY *>(key)));
86  }
87 };
88 
89 /// A typedef for an allocator for the string key/item allocation.
93 
94 /// @brief A thread-safe hash map which stores indexed shared items
95 ///
96 /// Each item in the hash map is reference counted. That is, if objects are
97 /// added multiple times, only a single object will be stored in the map.
98 ///
99 /// Removing an item from the hash map (by id or key) will decrement the
100 /// reference count on the item. When no longer referenced, the map will
101 /// automatically delete the item.
102 ///
103 /// As items are added to the map, each is assigned a unique id
104 /// (UT_IndexedHashMapItemId). Items can then be retrieved efficiently from
105 /// the map using the id (UT_IndexedHashMapT::get()).
106 ///
107 /// Many methods on the map are thread-safe, though some are not. The thread
108 /// safety of the methods is described in the comments.
109 ///
110 /// The KEY template parameter needs to have: @code
111 /// KEY(const KEY &src); // The copy constructor
112 /// uint hash() const; // A hash method
113 /// bool isEqual(const KEY &src) const; // A comparison operator
114 /// @endcode
115 /// For sorting, there should be a < operator defined on items.
116 ///
117 /// When adding items to an indexed hash map, only a single item is every
118 /// created for duplicate keys. To optimize addition, items can be created
119 /// only if the item will be added to the map. This is done through the
120 /// DEFER_ALLOC template parameter. With the default argument (which doesn't
121 /// allow deferred allocation), ITEM objects @b must be passed in the add()
122 /// method.
123 template <typename KEY, typename ITEM,
124  typename DEFER_ALLOC=ut_IndexedHashMapDeferNullAlloc>
126 {
127 protected:
128  /// The indexed hash map maintains all operations on internal types. This
129  /// allows the bulk of the code to be shared between template
130  /// instantiations.
132  { return static_cast<KEY *>(key); }
133  SYS_FORCE_INLINE const KEY *castKEY(const InternalKeyT *key) const
134  { return static_cast<const KEY *>(key); }
136  { return static_cast<ITEM *>(item); }
137  SYS_FORCE_INLINE const ITEM *castITEM(const InternalItemT *item) const
138  { return static_cast<const ITEM *>(item); }
139 
140  /// Methods for keys
141  virtual uint hash(const InternalKeyT *key) const
142  { return castKEY(key)->hash(); }
143  virtual bool areKeysEqual(const InternalKeyT *k1,
144  const InternalKeyT *k2) const
145  { return *castKEY(k1) == *castKEY(k2); }
146  virtual InternalKeyT *copyKey(const InternalKeyT *key) const
147  { return new KEY(*castKEY(key)); }
148  virtual void deleteKey(InternalKeyT *key) const
149  { delete castKEY(key); }
150 
151  virtual InternalItemT *newItem(const InternalKeyT *key) const
152  {
153  return DEFER_ALLOC::newItem(key);
154  }
155  virtual void deleteItem(InternalItemT *item) const
156  { delete castITEM(item); }
157  virtual bool isItemLessThan(const InternalItemT *a,
158  const InternalItemT *b) const
159  { return *castITEM(a) < *castITEM(b); }
160 
161 public:
162  UT_IndexedHashMapT(bool store_ids=true)
163  : UT_IndexedHashMap(store_ids)
164  {}
166  {
167  clear(); // Clear the map
168  }
169 
170  /// Return approximate memory usage
171  /// NOTE: *Not* including KEY or ITEM storage, even though the destructor
172  /// destroys both the KEY and ITEM objects, because the caller should know
173  /// better what KEY and ITEM are. If they can't vary in size, just
174  /// multiply by entries(); if they can, use begin() to iterate through.
175  int64 getMemoryUsage(bool inclusive) const
176  {
177  int64 mem = inclusive ? sizeof(*this) : 0;
178  mem += UT_IndexedHashMap::getMemoryUsage(false);
179  return mem;
180  }
181 
182  /// Add a new item to the map, returning the item actually stored in the
183  /// map. This may not be the item passed in if the map already contains
184  /// the object.
185  ///
186  /// If the item passed in is NULL, an item will be allocated using the
187  /// deferred allocator (see the DEFER_ALLOC template argument). The
188  /// default allocator does @b not allow for deferred construction and
189  /// requires the item to be passed in.
190  /// @note This is thread-safe
191  ITEM *add(const KEY &key, ITEM *item=NULL,
192  UT_IndexedHashMapItemId *id=NULL)
193  { return castITEM(_add(&key, item, id)); }
194 
195  /// Add reference to an existing item.
196  /// @param id Item index
197  /// @param inc The number of references to add.
198  /// It defaults to 1. If negative, the item may be
199  /// removed in which case it returns 0.
200  /// @note This item is thread-safe provided the item is exists in the map
201  /// @{
203  { return castITEM(_addReference(id, inc)); }
205  { return castITEM(_addReference(id, 1)); }
206  /// @}
207 
208  /// Find an item in the map.
209  /// @note This is thread-safe
210  ITEM *find(const KEY &key) const
211  { return castITEM(_find(&key)); }
212 
213  /// Given a key, find an item's id (or -1 if not found)
214  /// @note This is thread-safe
215  UT_IndexedHashMapItemId findId(const KEY &key) const
216  { return _findId(&key); }
217 
218  /// Find an item and its id. This is more efficient than calling find()
219  /// and findId() separately. Calling find() and findId() is also not
220  /// always thread-safe.
221  /// @note This is thread-safe
222  ITEM *find(const KEY &key, UT_IndexedHashMapItemId &id) const
223  { return castITEM(_findItemAndId(&key, id)); }
224 
225  /// Get the item which has the given id
226  /// @note This is thread-safe
227  ITEM *get(UT_IndexedHashMapItemId id) const
228  { return castITEM(_get(id)); }
229 
230  /// Get the n'th item in the list. This skips over holes and will return
231  /// items for a contiguous list of integers. For example: @code
232  /// for (int i = 0; ; ++i)
233  /// {
234  /// UT_IndexedHashMapItemId id;
235  /// ITEM *item = map.getOrderedItem(i, &id);
236  /// if (!item)
237  /// break;
238  /// }
239  /// @endcode
240  /// The @c UT_IndexedHashMapItemId's returned should be monotonic, but not
241  /// contiguous. If the @c id parameter is non-null, the id for the item
242  /// will be stored there.
243  /// @note This is @b not thread-safe
245  UT_IndexedHashMapItemId *id = NULL) const
246  { return castITEM(_getOrderedItem(index, id)); }
247 
248  /// Get the key associated with the given id
249  /// @note This is thread-safe
250  const KEY *getKey(UT_IndexedHashMapItemId id) const
251  { return castKEY(_getKey(id)); }
252 
253  /// Remove an item from the map. This dereferences the item in the map and
254  /// returns true if the item was deleted from the map. The method will
255  /// return false if the item was shared and is still in the map.
256  /// @note This is thread-safe
257  bool remove(const KEY &key)
258  { return _remove(&key); }
259 
260  /// Remove the item with the given id from the map.
261  /// @note This is thread-safe
263  { return _remove(id); }
264 
265  /// Replace an item at a given id.
266  ///
267  /// The existing item will be deleted from the table and the new item will
268  /// replace it.
269  /// The method will fail if there is currently no item at the given
270  /// location.
271  ///
272  /// The method will return the new id for the item. Usually, this will be
273  /// the same as the existing id, unless the new item already exists in the
274  /// map.
275  ///
276  /// If the item passed in is NULL, a new item will be called using newItem()
277  ///
278  /// @warning If the returned @c id does not match the @c id passed in, it's
279  /// the user's responsibility to update any references to the new id.
280  /// @note This is thread-safe
282  const KEY &key, ITEM *item=NULL)
283  { return _replaceItem(id, &key, item); }
284 
285  /// Replace the object given by the @c old_key with the value given by the
286  /// @c new_key.
287  ///
288  /// The @c old_key will be removed by the map.
289  ///
290  /// If the map stores id's, the @c new_key will be assigned the same id as
291  /// the @c old_key unless the @c new_key already exists in the map.
292  ///
293  /// The @c new_key object will inherit all references of the @c old_key.
294  ///
295  /// This method returns the id of the new item. This will be the same id
296  /// as the old object unless the @c new_key already exists in the map.
297  /// @note This is thread-safe
299  const KEY &new_key)
300  { return _replaceItem(&old_key, &new_key); }
301 
302  /// Extract the items into a list of ids and pointers to items. Items will
303  /// be appended to the lists. The function returns the number of items
304  /// added.
305  /// @note This is @b not thread-safe
308  UT_Array<ITEM *> &items
309  ) const
310  {
311  return _extractItems(ids,
312  reinterpret_cast< UT_Array<InternalItemT *> & >(items));
313  }
316  UT_Array<ITEM *> &items,
317  exint maxitems
318  ) const
319  {
320  return _extractItems(ids,
321  reinterpret_cast< UT_Array<InternalItemT *> & >(items),
322  maxitems);
323  }
324 
325  /// Extract an array of pointers to items.
326  ///
327  /// If there are id's associated with the items, the items will be stored
328  /// at their indexed location. The list of items may contain NULL pointers
329  /// for unused index entries.
330  ///
331  /// If there are no id's, the items will be extracted in arbitrary order
332  /// into a packed array.
333  ///
334  /// The function returns the number of items in the array.
335  /// @note This is @b not thread-safe
337  {
338  return _extractItems(
339  reinterpret_cast< UT_Array<InternalItemT *> & >(items));
340  }
341 
342 
343  /// @{
344  /// Convenience operators
346  { return get(id); }
347  ITEM *operator[](const KEY &k) const
348  { return find(k); }
350  { return get(id); }
351  ITEM *operator()(const KEY &k) const
352  { return find(k); }
353  /// @}
354 
355  /// Replaces the content of this with the content of src.
357  {
358  _replace(src);
359  }
360 };
361 
362 /// A string map
367 
368 #endif
SYS_FORCE_INLINE const KEY * castKEY(const InternalKeyT *key) const
UT_IndexedHashMapItemId replaceItem(const KEY &old_key, const KEY &new_key)
GLuint id
Definition: glew.h:1679
GLenum src
Definition: glew.h:2410
UT_IndexedHashMapItemKeyContainer(const UT_IndexedHashMapItemKeyContainer &i)
UT_IndexedHashMapT(bool store_ids=true)
SYS_FORCE_INLINE KEY * castKEY(InternalKeyT *key) const
GLuint index
Definition: glew.h:1814
InternalItemT * _get(UT_IndexedHashMapItemId id) const
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:9477
void _replace(const UT_IndexedHashMap &src)
ITEM * find(const KEY &key) const
InternalItemT * _addReference(UT_IndexedHashMapItemId id, int inc)
UT_IndexedHashMapItemId _replaceItem(UT_IndexedHashMapItemId id, const InternalKeyT *key, InternalItemT *new_item=NULL)
#define UT_API
Definition: UT_API.h:13
UT_IndexedHashMapItemId replaceItem(UT_IndexedHashMapItemId id, const KEY &key, ITEM *item=NULL)
static UT_IndexedHashMap::InternalItemT * newItem(const UT_IndexedHashMap::InternalKeyT *key)
Return NULL (don't allow deferred construction).
exint extractItems(UT_Array< UT_IndexedHashMapItemId > &ids, UT_Array< ITEM * > &items) const
exint _extractItems(UT_Array< UT_IndexedHashMapItemId > &ids, UT_Array< InternalItemT * > &items, exint maxitems) const
A thread-safe hash map which stores indexed shared items.
long long int64
Definition: SYS_Types.h:111
exint extractItems(UT_Array< UT_IndexedHashMapItemId > &ids, UT_Array< ITEM * > &items, exint maxitems) const
ITEM * getOrderedItem(exint index, UT_IndexedHashMapItemId *id=NULL) const
UT_IndexedHashMapItemKeyContainer< UT_IndexedHashMapStringKey > UT_IndexedHashMapStringItem
bool _remove(const InternalKeyT *key)
virtual void deleteKey(InternalKeyT *key) const
int64 exint
Definition: SYS_Types.h:120
UT_IndexedHashMapItemKeyContainer & operator=(const UT_IndexedHashMapItemKeyContainer &src)
InternalItemT * _getOrderedItem(exint index, UT_IndexedHashMapItemId *id) const
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
int64 getMemoryUsage(bool inclusive) const
Return approximate memory usage (not including key or item storage)
ITEM * addReference(UT_IndexedHashMapItemId id, int inc)
UT_StringHolder UT_IndexedHashMapStringKey
static UT_IndexedHashMap::InternalItemT * newItem(const UT_IndexedHashMap::InternalKeyT *key)
virtual bool areKeysEqual(const InternalKeyT *k1, const InternalKeyT *k2) const
virtual uint hash(const InternalKeyT *key) const
Methods for keys.
exint _findId(const InternalKeyT *key) const
virtual InternalItemT * newItem(const InternalKeyT *key) const
bool operator<(const UT_IndexedHashMapItemKeyContainer &i) const
unsigned int uint
Definition: SYS_Types.h:44
ITEM * operator[](const KEY &k) const
SYS_FORCE_INLINE const ITEM * castITEM(const InternalItemT *item) const
An allocator object which dis-allows deferred allocation of items.
GLdouble GLdouble GLdouble b
Definition: glew.h:9122
const InternalKeyT * _getKey(UT_IndexedHashMapItemId id) const
ITEM * operator()(const KEY &k) const
virtual bool isItemLessThan(const InternalItemT *a, const InternalItemT *b) const
virtual InternalKeyT * copyKey(const InternalKeyT *key) const
InternalItemT * _add(const InternalKeyT *key, InternalItemT *item=NULL, UT_IndexedHashMapItemId *id=NULL)
void replace(const UT_IndexedHashMapT< KEY, ITEM, DEFER_ALLOC > &src)
Replaces the content of this with the content of src.
SYS_FORCE_INLINE ITEM * castITEM(InternalItemT *item) const
A thread-safe hash map which stores indexed shared items.
ITEM * operator[](UT_IndexedHashMapItemId id) const
const GLuint * ids
Definition: glew.h:1684
ITEM * find(const KEY &key, UT_IndexedHashMapItemId &id) const
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:135
UT_IndexedHashMapItemId findId(const KEY &key) const
ITEM * operator()(UT_IndexedHashMapItemId id) const
virtual void deleteItem(InternalItemT *item) const
InternalItemT * _find(const InternalKeyT *key) const
InternalItemT * _findItemAndId(const InternalKeyT *key, UT_IndexedHashMapItemId &id) const
int64 getMemoryUsage(bool inclusive) const
int UT_IndexedHashMapItemId
Each item in the shared map is assigned a unique id.
const KEY * getKey(UT_IndexedHashMapItemId id) const
exint extractItems(UT_Array< ITEM * > &items) const
ITEM * add(const KEY &key, ITEM *item=NULL, UT_IndexedHashMapItemId *id=NULL)
ITEM * addReference(UT_IndexedHashMapItemId id)