]> git.sesse.net Git - casparcg/blob - concrt_extras/concurrent_unordered_map.h
dependencies: Cleanup
[casparcg] / concrt_extras / concurrent_unordered_map.h
1 /***\r
2 * ==++==\r
3 *\r
4 * Copyright (c) Microsoft Corporation.  All rights reserved.\r
5\r
6 * ==--==\r
7 * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+\r
8 *\r
9 * concurrent_unordered_map.h\r
10 *\r
11 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r
12 ****/\r
13 #pragma once\r
14 \r
15 #include <utility>\r
16 #include "internal_concurrent_hash.h"\r
17 \r
18 #if !(defined(_M_AMD64) || defined(_M_IX86))\r
19     #error ERROR: Concurrency Runtime is supported only on X64 and X86 architectures.\r
20 #endif\r
21 \r
22 #if defined(_M_CEE)\r
23     #error ERROR: Concurrency Runtime is not supported when compiling /clr.\r
24 #endif\r
25 \r
26 #pragma pack(push,_CRT_PACKING)\r
27 \r
28 namespace Concurrency\r
29 {\r
30 namespace details\r
31 {\r
32 // Template class for hash map traits\r
33 template<typename _Key_type, typename _Element_type, typename _Key_comparator, typename _Allocator_type, bool _Allow_multimapping>\r
34 class _Concurrent_unordered_map_traits : public std::_Container_base\r
35 {\r
36 public:\r
37     typedef std::pair<_Key_type, _Element_type> _Value_type;\r
38     typedef std::pair<const _Key_type, _Element_type> value_type;\r
39     typedef _Key_type key_type;\r
40     typedef _Key_comparator key_compare;\r
41 \r
42     typedef typename _Allocator_type::template rebind<value_type>::other allocator_type;\r
43 \r
44     enum\r
45     {\r
46         _M_allow_multimapping = _Allow_multimapping\r
47     };\r
48 \r
49     _Concurrent_unordered_map_traits() : _M_comparator()\r
50     {\r
51     }\r
52 \r
53     _Concurrent_unordered_map_traits(const key_compare& _Traits) : _M_comparator(_Traits)\r
54     {\r
55     }\r
56 \r
57     class value_compare : public std::binary_function<value_type, value_type, bool>\r
58     {\r
59         friend class _Concurrent_unordered_map_traits<_Key_type, _Element_type, _Key_comparator, _Allocator_type, _Allow_multimapping>;\r
60 \r
61     public:\r
62         bool operator()(const value_type& _Left, const value_type& _Right) const\r
63         {\r
64             return (_M_comparator(_Left.first, _Right.first));\r
65         }\r
66 \r
67         value_compare(const key_compare& _Traits) : _M_comparator(_Traits)\r
68         {\r
69         }\r
70 \r
71     protected:\r
72         key_compare _M_comparator;    // the comparator predicate for keys\r
73     };\r
74 \r
75     template<class _Type1, class _Type2>\r
76     static const _Type1& _Key_function(const std::pair<_Type1, _Type2>& _Value)\r
77     {\r
78         return (_Value.first);\r
79     }\r
80     key_compare _M_comparator; // the comparator predicate for keys\r
81 };\r
82 } // namespace details;\r
83 \r
84 /// <summary>\r
85 ///     The <c>concurrent_unordered_map</c> class is an concurrency-safe container that controls a varying-length sequence of \r
86 ///     elements of type std::pair<const _Key_type, _Element_type>. The sequence is represented in a way that enables \r
87 ///     concurrency-safe append, element access, iterator access and iterator traversal operations.\r
88 /// </summary>\r
89 /// <typeparam name="_Key_type">\r
90 ///     The key type.\r
91 /// </typeparam>\r
92 /// <typeparam name="_Element_type">\r
93 ///     The mapped type.\r
94 /// </typeparam>\r
95 /// <typeparam name="_Hasher">\r
96 ///     The hash function object type. This argument is optional and the default value is\r
97 ///     tr1::hash&lt;</c><typeparamref name="_Key_type"/><c>&gt;</c>.\r
98 /// </typeparam>\r
99 /// <typeparam name="_Key_equality">\r
100 ///     The equality comparison function object type. This argument is optional and the default value is\r
101 ///     <c>equal_to&lt;</c><typeparamref name="_Key_type"/><c>&gt;</c>.\r
102 /// </typeparam>\r
103 /// <typeparam name="_Allocator_type">\r
104 ///     The type that represents the stored allocator object that encapsulates details about the allocation and\r
105 ///     deallocation of memory for the concurrent vector. This argument is optional and the default value is\r
106 ///     <c>allocator&lt;</c><typeparamref name="_Key_type"/>, <typeparamref name="_Element_type"/><c>&gt;</c>.\r
107 /// </typeparam>\r
108 /// <remarks>\r
109 ///     For detailed information on the <c>concurrent_unordered_map</c> class, see <see cref="Parallel Containers and Objects"/>.\r
110 /// </remarks>\r
111 /// <seealso cref="Parallel Containers and Objects"/>\r
112 /**/\r
113 template <typename _Key_type, typename _Element_type, typename _Hasher = std::tr1::hash<_Key_type>, typename _Key_equality = std::equal_to<_Key_type>, typename _Allocator_type = std::allocator<std::pair<const _Key_type, _Element_type> > >\r
114 class concurrent_unordered_map : public details::_Concurrent_hash< details::_Concurrent_unordered_map_traits<_Key_type, _Element_type, details::_Hash_compare<_Key_type, _Hasher, _Key_equality>, _Allocator_type, false> >\r
115 {\r
116 public:\r
117     // Base type definitions\r
118     typedef concurrent_unordered_map<_Key_type, _Element_type, _Hasher, _Key_equality, _Allocator_type> _Mytype;\r
119     typedef details::_Hash_compare<_Key_type, _Hasher, _Key_equality> _Mytraits;\r
120     typedef details::_Concurrent_hash< details::_Concurrent_unordered_map_traits<_Key_type, _Element_type, _Mytraits, _Allocator_type, false> > _Mybase;\r
121 \r
122     // Type definitions\r
123     typedef _Key_type key_type;\r
124     typedef typename _Mybase::value_type value_type;\r
125     typedef _Element_type mapped_type;\r
126     typedef _Hasher hasher;\r
127     typedef _Key_equality key_equal;\r
128     typedef _Mytraits key_compare;\r
129 \r
130     typedef typename _Mybase::allocator_type allocator_type;\r
131     typedef typename _Mybase::pointer pointer;\r
132     typedef typename _Mybase::const_pointer const_pointer;\r
133     typedef typename _Mybase::reference reference;\r
134     typedef typename _Mybase::const_reference const_reference;\r
135 \r
136     typedef typename _Mybase::size_type size_type;\r
137     typedef typename _Mybase::difference_type difference_type;\r
138 \r
139     typedef typename _Mybase::iterator iterator;\r
140     typedef typename _Mybase::const_iterator const_iterator;\r
141     typedef typename _Mybase::iterator local_iterator;\r
142     typedef typename _Mybase::const_iterator const_local_iterator;\r
143 \r
144     /// <summary>\r
145     ///     Constructs a concurrent unordered map.\r
146     /// </summary>\r
147     /// <param name="_Number_of_buckets">\r
148     ///     The initial number of buckets for this unordered map.\r
149     /// </param>\r
150     /// <param name="_Hasher">\r
151     ///     The hash function for this unordered map.\r
152     /// </param>\r
153     /// <param name="_Key_equality">\r
154     ///     The equality comparison function for this unordered map.\r
155     /// </param>\r
156     /// <param name="_Allocator">\r
157     ///     The allocator for this unordered map.\r
158     /// </param>\r
159     /// <remarks>\r
160     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered map.\r
161     ///     <para>The first constructor specifies an empty initial map and explicitly specifies the number of buckets,\r
162     ///     hash function, equality function and allocator type to be used.</para>\r
163     ///     <para>The second constructor specifies an allocator for the unordered map.<para>\r
164     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
165     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
166     ///     <para>The last constructor specifies a move of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
167     /// </remarks>\r
168     /**/\r
169     explicit concurrent_unordered_map(size_type _Number_of_buckets = 8, const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(),\r
170         const allocator_type& _Allocator = allocator_type())\r
171         : _Mybase(_Number_of_buckets, key_compare(_Hasher, _Key_equality), _Allocator)\r
172     {\r
173         this->rehash(_Number_of_buckets);\r
174     }\r
175 \r
176     /// <summary>\r
177     ///     Constructs a concurrent unordered map.\r
178     /// </summary>\r
179     /// <param name="_Allocator">\r
180     ///     The allocator for this unordered map.\r
181     /// </param>\r
182     /// <remarks>\r
183     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered map.\r
184     ///     <para>The first constructor specifies an empty initial map and explicitly specifies the number of buckets,\r
185     ///     hash function, equality function and allocator type to be used.</para>\r
186     ///     <para>The second constructor specifies an allocator for the unordered map.<para>\r
187     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
188     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
189     ///     <para>The last constructor specifies a move of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
190     /// </remarks>\r
191     /**/\r
192     concurrent_unordered_map(const allocator_type& _Allocator) : _Mybase(8, key_compare(), _Allocator)\r
193     {\r
194     }\r
195 \r
196     /// <summary>\r
197     ///     Constructs a concurrent unordered map.\r
198     /// </summary>\r
199     /// <typeparam name="_Iterator">\r
200     ///     The type of the input iterator.\r
201     /// </typeparam>\r
202     /// <param name="_Begin">\r
203     ///     Position of the first element in the range of elements to be copied.\r
204     /// </param>\r
205     /// <param name="_End">\r
206     ///     Position of the first element beyond the range of elements to be copied.\r
207     /// </param>\r
208     /// <param name="_Number_of_buckets">\r
209     ///     The initial number of buckets for this unordered map.\r
210     /// </param>\r
211     /// <param name="_Hasher">\r
212     ///     The hash function for this unordered map.\r
213     /// </param>\r
214     /// <param name="_Key_equality">\r
215     ///     The equality comparison function for this unordered map.\r
216     /// </param>\r
217     /// <param name="_Allocator">\r
218     ///     The allocator for this unordered map.\r
219     /// </param>\r
220     /// <remarks>\r
221     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered map.\r
222     ///     <para>The first constructor specifies an empty initial map and explicitly specifies the number of buckets,\r
223     ///     hash function, equality function and allocator type to be used.</para>\r
224     ///     <para>The second constructor specifies an allocator for the unordered map.<para>\r
225     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
226     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
227     ///     <para>The last constructor specifies a move of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
228     /// </remarks>\r
229     /**/\r
230     template <typename _Iterator>\r
231     concurrent_unordered_map(_Iterator _Begin, _Iterator _End, size_type _Number_of_buckets = 8, const hasher& _Hasher = hasher(),\r
232         const key_equal& _Key_equality = key_equal(), const allocator_type& _Allocator = allocator_type())\r
233         : _Mybase(_Number_of_buckets, key_compare(), allocator_type())\r
234     {\r
235         this->rehash(_Number_of_buckets);\r
236         for (; _Begin != _End; ++_Begin)\r
237         {\r
238             _Mybase::insert(*_Begin);\r
239         }\r
240     }\r
241 \r
242     /// <summary>\r
243     ///     Constructs a concurrent unordered map.\r
244     /// </summary>\r
245     /// <param name="_Umap">\r
246     ///     The source <c>concurrent_unordered_map</c> object to copy or move elements from.\r
247     /// </param>\r
248     /// <remarks>\r
249     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered map.\r
250     ///     <para>The first constructor specifies an empty initial map and explicitly specifies the number of buckets,\r
251     ///     hash function, equality function and allocator type to be used.</para>\r
252     ///     <para>The second constructor specifies an allocator for the unordered map.<para>\r
253     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
254     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
255     ///     <para>The last constructor specifies a move of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
256     /// </remarks>\r
257     /**/\r
258     concurrent_unordered_map(const concurrent_unordered_map& _Umap) : _Mybase(_Umap)\r
259     {\r
260     }\r
261 \r
262     /// <summary>\r
263     ///     Constructs a concurrent unordered map.\r
264     /// </summary>\r
265     /// <param name="_Umap">\r
266     ///     The source <c>concurrent_unordered_map</c> object to copy or move elements from.\r
267     /// </param>\r
268     /// <param name="_Allocator">\r
269     ///     The allocator for this unordered map.\r
270     /// </param>\r
271     /// <remarks>\r
272     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered map.\r
273     ///     <para>The first constructor specifies an empty initial map and explicitly specifies the number of buckets,\r
274     ///     hash function, equality function and allocator type to be used.</para>\r
275     ///     <para>The second constructor specifies an allocator for the unordered map.<para>\r
276     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
277     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
278     ///     <para>The last constructor specifies a move of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
279     /// </remarks>\r
280     /**/\r
281     concurrent_unordered_map(const concurrent_unordered_map& _Umap, const allocator_type& _Allocator) : _Mybase(_Umap, _Allocator)\r
282     {\r
283     }\r
284 \r
285     /// <summary>\r
286     ///     Constructs a concurrent unordered map.\r
287     /// </summary>\r
288     /// <param name="_Umap">\r
289     ///     The source <c>concurrent_unordered_map</c> object to copy or move elements from.\r
290     /// </param>\r
291     /// <remarks>\r
292     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered map.\r
293     ///     <para>The first constructor specifies an empty initial map and explicitly specifies the number of buckets,\r
294     ///     hash function, equality function and allocator type to be used.</para>\r
295     ///     <para>The second constructor specifies an allocator for the unordered map.<para>\r
296     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
297     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
298     ///     <para>The last constructor specifies a move of the concurrent unordered map <paramref name="_Umap"/>.</para>\r
299     /// </remarks>\r
300     /**/\r
301     concurrent_unordered_map(concurrent_unordered_map&& _Umap) : _Mybase(std::move(_Umap))\r
302     {\r
303     }\r
304 \r
305     /// <summary>\r
306     ///     Assigns the contents of another <c>concurrent_unordered_map</c> object to this one. This method is not concurrency-safe.\r
307     /// </summary>\r
308     /// <param name="_Umap">\r
309     ///     The source <c>concurrent_unordered_map</c> object.\r
310     /// </param>\r
311     /// <returns>\r
312     ///     A reference to this <c>concurrent_unordered_map</c> object.\r
313     /// </returns>\r
314     /// <remarks>\r
315     ///     After erasing any existing elements a concurrent vector, <c>operator=</c> either copies or moves the contents of <paramref name="_Umap"/> into\r
316     ///     the concurrent vector.\r
317     /// </remarks>\r
318     /**/\r
319     concurrent_unordered_map& operator=(const concurrent_unordered_map& _Umap)\r
320     {\r
321         _Mybase::operator=(_Umap);\r
322         return (*this);\r
323     }\r
324 \r
325     /// <summary>\r
326     ///     Assigns the contents of another <c>concurrent_unordered_map</c> object to this one. This method is not concurrency-safe.\r
327     /// </summary>\r
328     /// <param name="_Umap">\r
329     ///     The source <c>concurrent_unordered_map</c> object.\r
330     /// </param>\r
331     /// <returns>\r
332     ///     A reference to this <c>concurrent_unordered_map</c> object.\r
333     /// </returns>\r
334     /// <remarks>\r
335     ///     After erasing any existing elements in a concurrent vector, <c>operator=</c> either copies or moves the contents of <paramref name="_Umap"/> into\r
336     ///     the concurrent vector.\r
337     /// </remarks>\r
338     /**/\r
339     concurrent_unordered_map& operator=(concurrent_unordered_map&& _Umap)\r
340     {\r
341         _Mybase::operator=(std::move(_Umap));\r
342         return (*this);\r
343     }\r
344 \r
345     /// <summary>\r
346     ///     Erases elements from the <c>concurrent_unordered_map</c>. This method is not concurrency-safe.\r
347     /// </summary>\r
348     /// <param name="_Where">\r
349     ///     The iterator position to erase from.\r
350     /// </param>\r
351     /// <remarks>\r
352     ///     The first function erases an element from the map given an iterator position.\r
353     ///     <para>The second function erases an element matching a key</para>\r
354     ///     <para>The third function erases elements given an iterator begin and end position</para>\r
355     /// </remarks>\r
356     /// <returns>\r
357     ///     The iterator for this <c>concurrent_unordered_map</c> object.\r
358     /// </returns>\r
359     /**/\r
360     iterator unsafe_erase(const_iterator _Where)\r
361     {\r
362         return _Mybase::unsafe_erase(_Where);\r
363     }\r
364 \r
365     /// <summary>\r
366     ///     Erases elements from the <c>concurrent_unordered_map</c>. This method is not concurrency-safe.\r
367     /// </summary>\r
368     /// <param name="_Keyval">\r
369     ///     The key to erase.\r
370     /// </param>\r
371     /// <remarks>\r
372     ///     The first function erases an element from the map given an iterator position.\r
373     ///     <para>The second function erases an element matching a key</para>\r
374     ///     <para>The third function erases elements given an iterator begin and end position</para>\r
375     /// </remarks>\r
376     /// <returns>\r
377     ///     The count of elements erased from this <c>concurrent_unordered_map</c> object.\r
378     /// </returns>\r
379     /**/\r
380     size_type unsafe_erase(const key_type& _Keyval)\r
381     {\r
382         return _Mybase::unsafe_erase(_Keyval);\r
383     }\r
384 \r
385     /// <summary>\r
386     ///     Erases elements from the <c>concurrent_unordered_map</c>. This method is not concurrency-safe.\r
387     /// </summary>\r
388     /// <param name="_Begin">\r
389     ///     Position of the first element in the range of elements to be erased.\r
390     /// </param>\r
391     /// <param name="_End">\r
392     ///     Position of the first element beyond the range of elements to be erased.\r
393     /// </param>\r
394     /// <remarks>\r
395     ///     The first function erases an element from the map given an iterator position.\r
396     ///     <para>The second function erases an element matching a key</para>\r
397     ///     <para>The third function erases elements given an iterator begin and end position</para>\r
398     /// </remarks>\r
399     /// <returns>\r
400     ///     The iterator for this <c>concurrent_unordered_map</c> object.\r
401     /// </returns>\r
402     /**/\r
403     iterator unsafe_erase(const_iterator _Begin, const_iterator _End)\r
404     {\r
405         return _Mybase::unsafe_erase(_Begin, _End);\r
406     }\r
407 \r
408     /// <summary>\r
409     ///     Swaps the contents of two <c>concurrent_unordered_map</c> objects. \r
410     ///     This method is not concurrency-safe.\r
411     /// </summary>\r
412     /// <param name="_Umap">\r
413     ///     The <c>concurrent_unordered_map</c> object to swap with.\r
414     /// </param>\r
415     /**/\r
416     void swap(concurrent_unordered_map& _Umap)\r
417     {\r
418         _Mybase::swap(_Umap);\r
419     }\r
420 \r
421     // Observers\r
422     /// <summary>\r
423     ///     The hash function object.\r
424     /// </summary>\r
425     /**/\r
426     hasher hash_function() const\r
427     {\r
428         return _M_comparator._M_hash_object;\r
429     }\r
430 \r
431     /// <summary>\r
432     ///     The equality comparison function object.\r
433     /// </summary>\r
434     /**/\r
435     key_equal key_eq() const\r
436     {\r
437         return _M_comparator._M_key_compare_object;\r
438     }\r
439 \r
440     /// <summary>\r
441     ///     Provides access to the element at the given key in the concurrent unordered map. This method is concurrency-safe.\r
442     /// </summary>\r
443     /// <param name="_Keyval">\r
444     ///     The key of the element to be retrieved.\r
445     /// </param>\r
446     /// <returns>\r
447     ///     A element mapped to by the key.\r
448     /// </returns>\r
449     /**/\r
450     mapped_type& operator[](const key_type& _Keyval)\r
451     {\r
452         iterator _Where = find(_Keyval);\r
453 \r
454         if (_Where == end())\r
455         {\r
456             _Where = insert(std::pair<key_type, mapped_type>(std::move(_Keyval), mapped_type())).first;\r
457         }\r
458 \r
459         return ((*_Where).second);\r
460     }\r
461 \r
462     /// <summary>\r
463     ///     Provides access to the element at the given key in the concurrent unordered map. This method is concurrency-safe.\r
464     /// </summary>\r
465     /// <param name="_Keyval">\r
466     ///     The key of the element to be retrieved.\r
467     /// </param>\r
468     /// <returns>\r
469     ///     A element mapped to by the key.\r
470     /// </returns>\r
471     /**/\r
472     mapped_type& at(const key_type& _Keyval)\r
473     {\r
474         iterator _Where = find(_Keyval);\r
475 \r
476         if (_Where == end())\r
477         {\r
478             throw std::out_of_range("invalid concurrent_unordered_map<K, T> key");\r
479         }\r
480 \r
481         return ((*_Where).second);\r
482     }\r
483 \r
484     /// <summary>\r
485     ///     Provides read access to the element at the given key in the concurrent unordered map. This method is concurrency-safe.\r
486     /// </summary>\r
487     /// <param name="_Keyval">\r
488     ///     The key of the element to be retrieved.\r
489     /// </param>\r
490     /// <returns>\r
491     ///     A element mapped to by the key.\r
492     /// </returns>\r
493     /**/\r
494     const mapped_type& at(const key_type& _Keyval) const\r
495     {\r
496         const_iterator _Where = find(_Keyval);\r
497 \r
498         if (_Where == end())\r
499         {\r
500             throw std::out_of_range("invalid concurrent_unordered_map<K, T> key");\r
501         }\r
502 \r
503         return ((*_Where).second);\r
504     }\r
505 };\r
506 \r
507 /// <summary>\r
508 ///     The <c>concurrent_unordered_multimap</c> class is an concurrency-safe container that controls a varying-length sequence of \r
509 ///     elements of type std::pair<const _Key_type, _Element_type>. The sequence is represented in a way that enables \r
510 ///     concurrency-safe append, element access, iterator access and iterator traversal operations.\r
511 /// </summary>\r
512 /// <typeparam name="_Key_type">\r
513 ///     The key type.\r
514 /// </typeparam>\r
515 /// <typeparam name="_Element_type">\r
516 ///     The mapped type.\r
517 /// </typeparam>\r
518 /// <typeparam name="_Hasher">\r
519 ///     The hash function object type. This argument is optional and the default value is\r
520 ///     tr1::hash&lt;</c><typeparamref name="_Key_type"/><c>&gt;</c>.\r
521 /// </typeparam>\r
522 /// <typeparam name="_Key_equality">\r
523 ///     The equality comparison function object type. This argument is optional and the default value is\r
524 ///     <c>equal_to&lt;</c><typeparamref name="_Key_type"/><c>&gt;</c>.\r
525 /// </typeparam>\r
526 /// <typeparam name="_Allocator_type">\r
527 ///     The type that represents the stored allocator object that encapsulates details about the allocation and\r
528 ///     deallocation of memory for the concurrent vector. This argument is optional and the default value is\r
529 ///     <c>allocator&lt;</c><typeparamref name="_Key_type"/>, <typeparamref name="_Element_type"/><c>&gt;</c>.\r
530 /// </typeparam>\r
531 /// <remarks>\r
532 ///     For detailed information on the <c>concurrent_unordered_multimap</c> class, see <see cref="Parallel Containers and Objects"/>.\r
533 /// </remarks>\r
534 /// <seealso cref="Parallel Containers and Objects"/>\r
535 /**/\r
536 template <typename _Key_type, typename _Element_type, typename _Hasher = std::tr1::hash<_Key_type>, typename _Key_equality = std::equal_to<_Key_type>, typename _Allocator_type = std::allocator<std::pair<const _Key_type, _Element_type> > >\r
537 class concurrent_unordered_multimap : public details::_Concurrent_hash< details::_Concurrent_unordered_map_traits<_Key_type, _Element_type, details::_Hash_compare<_Key_type, _Hasher, _Key_equality>, _Allocator_type, true> >\r
538 {\r
539 public:\r
540     // Base type definitions\r
541     typedef concurrent_unordered_multimap<_Key_type, _Element_type, _Hasher, _Key_equality, _Allocator_type> _Mytype;\r
542     typedef details::_Hash_compare<_Key_type, _Hasher, _Key_equality> _Mytraits;\r
543     typedef details::_Concurrent_hash< details::_Concurrent_unordered_map_traits<_Key_type, _Element_type, _Mytraits, _Allocator_type, true> > _Mybase;\r
544 \r
545     // Type definitions\r
546     typedef _Key_type key_type;\r
547     typedef typename _Mybase::value_type value_type;\r
548     typedef _Element_type mapped_type;\r
549     typedef _Hasher hasher;\r
550     typedef _Key_equality key_equal;\r
551     typedef _Mytraits key_compare;\r
552 \r
553     typedef typename _Mybase::allocator_type allocator_type;\r
554     typedef typename _Mybase::pointer pointer;\r
555     typedef typename _Mybase::const_pointer const_pointer;\r
556     typedef typename _Mybase::reference reference;\r
557     typedef typename _Mybase::const_reference const_reference;\r
558 \r
559     typedef typename _Mybase::size_type size_type;\r
560     typedef typename _Mybase::difference_type difference_type;\r
561 \r
562     typedef typename _Mybase::iterator iterator;\r
563     typedef typename _Mybase::const_iterator const_iterator;\r
564     typedef typename _Mybase::iterator local_iterator;\r
565     typedef typename _Mybase::const_iterator const_local_iterator;\r
566 \r
567     /// <summary>\r
568     ///     Constructs a concurrent unordered multimap.\r
569     /// </summary>\r
570     /// <param name="_Number_of_buckets">\r
571     ///     The initial number of buckets for this unordered multimap.\r
572     /// </param>\r
573     /// <param name="_Hasher">\r
574     ///     The hash function for this unordered multimap.\r
575     /// </param>\r
576     /// <param name="_Key_equality">\r
577     ///     The equality comparison function for this unordered multimap.\r
578     /// </param>\r
579     /// <param name="_Allocator">\r
580     ///     The allocator for this unordered multimap.\r
581     /// </param>\r
582     /// <remarks>\r
583     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered multimap.\r
584     ///     <para>The first constructor specifies an empty initial multimap and explicitly specifies the number of buckets,\r
585     ///     hash function, equality function and allocator type to be used.</para>\r
586     ///     <para>The second constructor specifies an allocator for the unordered multimap.<para>\r
587     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
588     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
589     ///     <para>The last constructor specifies a move of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
590     /// </remarks>\r
591     /**/\r
592     explicit concurrent_unordered_multimap(size_type _Number_of_buckets = 8, const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(),\r
593         const allocator_type& _Allocator = allocator_type())\r
594         : _Mybase(_Number_of_buckets, key_compare(_Hasher, _Key_equality), _Allocator)\r
595     {\r
596         this->rehash(_Number_of_buckets);\r
597     }\r
598 \r
599     /// <summary>\r
600     ///     Constructs a concurrent unordered multimap.\r
601     /// </summary>\r
602     /// <param name="_Allocator">\r
603     ///     The allocator for this unordered multimap.\r
604     /// </param>\r
605     /// <remarks>\r
606     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered multimap.\r
607     ///     <para>The first constructor specifies an empty initial multimap and explicitly specifies the number of buckets,\r
608     ///     hash function, equality function and allocator type to be used.</para>\r
609     ///     <para>The second constructor specifies an allocator for the unordered multimap.<para>\r
610     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
611     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
612     ///     <para>The last constructor specifies a move of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
613     /// </remarks>\r
614     /**/\r
615     concurrent_unordered_multimap(const allocator_type& _Allocator) : _Mybase(8, key_compare(), _Allocator)\r
616     {\r
617     }\r
618 \r
619     /// <summary>\r
620     ///     Constructs a concurrent unordered multimap.\r
621     /// </summary>\r
622     /// <typeparam name="_Iterator">\r
623     ///     The type of the input iterator.\r
624     /// </typeparam>\r
625     /// <param name="_Begin">\r
626     ///     Position of the first element in the range of elements to be copied.\r
627     /// </param>\r
628     /// <param name="_End">\r
629     ///     Position of the first element beyond the range of elements to be copied.\r
630     /// </param>\r
631     /// <param name="_Number_of_buckets">\r
632     ///     The initial number of buckets for this unordered multimap.\r
633     /// </param>\r
634     /// <param name="_Hasher">\r
635     ///     The hash function for this unordered multimap.\r
636     /// </param>\r
637     /// <param name="_Key_equality">\r
638     ///     The equality comparison function for this unordered multimap.\r
639     /// </param>\r
640     /// <param name="_Allocator">\r
641     ///     The allocator for this unordered multimap.\r
642     /// </param>\r
643     /// <remarks>\r
644     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered multimap.\r
645     ///     <para>The first constructor specifies an empty initial multimap and explicitly specifies the number of buckets,\r
646     ///     hash function, equality function and allocator type to be used.</para>\r
647     ///     <para>The second constructor specifies an allocator for the unordered multimap.<para>\r
648     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
649     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
650     ///     <para>The last constructor specifies a move of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
651     /// </remarks>\r
652     /**/\r
653     template <typename _Iterator>\r
654     concurrent_unordered_multimap(_Iterator _Begin, _Iterator _End, size_type _Number_of_buckets = 8, const hasher& _Hasher = hasher(),\r
655         const key_equal& _Key_equality = key_equal(), const allocator_type& _Allocator = allocator_type())\r
656         : _Mybase(_Number_of_buckets, key_compare(), allocator_type())\r
657     {\r
658         this->rehash(_Number_of_buckets);\r
659         for (; _Begin != _End; ++_Begin)\r
660         {\r
661             _Mybase::insert(*_Begin);\r
662         }\r
663     }\r
664 \r
665     /// <summary>\r
666     ///     Constructs a concurrent unordered multimap.\r
667     /// </summary>\r
668     /// <param name="_Umap">\r
669     ///     The source <c>concurrent_unordered_multimap</c> object to copy elements from.\r
670     /// </param>\r
671     /// <remarks>\r
672     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered multimap.\r
673     ///     <para>The first constructor specifies an empty initial multimap and explicitly specifies the number of buckets,\r
674     ///     hash function, equality function and allocator type to be used.</para>\r
675     ///     <para>The second constructor specifies an allocator for the unordered multimap.<para>\r
676     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
677     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
678     ///     <para>The last constructor specifies a move of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
679     /// </remarks>\r
680     /**/\r
681     concurrent_unordered_multimap(const concurrent_unordered_multimap& _Umap) : _Mybase(_Umap)\r
682     {\r
683     }\r
684 \r
685     /// <summary>\r
686     ///     Constructs a concurrent unordered multimap.\r
687     /// </summary>\r
688     /// <param name="_Umap">\r
689     ///     The source <c>concurrent_unordered_multimap</c> object to copy elements from.\r
690     /// </param>\r
691     /// <param name="_Allocator">\r
692     ///     The allocator for this unordered multimap.\r
693     /// </param>\r
694     /// <remarks>\r
695     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered multimap.\r
696     ///     <para>The first constructor specifies an empty initial multimap and explicitly specifies the number of buckets,\r
697     ///     hash function, equality function and allocator type to be used.</para>\r
698     ///     <para>The second constructor specifies an allocator for the unordered multimap.<para>\r
699     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
700     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
701     ///     <para>The last constructor specifies a move of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
702     /// </remarks>\r
703     /**/\r
704     concurrent_unordered_multimap(const concurrent_unordered_multimap& _Umap, const allocator_type& _Allocator) : _Mybase(_Umap, _Allocator)\r
705     {\r
706     }\r
707 \r
708     /// <summary>\r
709     ///     Constructs a concurrent unordered multimap.\r
710     /// </summary>\r
711     /// <param name="_Umap">\r
712     ///     The source <c>concurrent_unordered_multimap</c> object to copy elements from.\r
713     /// </param>\r
714     /// <remarks>\r
715     ///     All constructors store an allocator object <paramref name="_Allocator"/> and initialize the unordered multimap.\r
716     ///     <para>The first constructor specifies an empty initial multimap and explicitly specifies the number of buckets,\r
717     ///     hash function, equality function and allocator type to be used.</para>\r
718     ///     <para>The second constructor specifies an allocator for the unordered multimap.<para>\r
719     ///     <para>The third constructor specifies values supplied by the iterator range [<paramref name="_Begin"/>, <paramref name="_End"/>).</para>\r
720     ///     <para>The fourth and fifth constructors specify a copy of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
721     ///     <para>The last constructor specifies a move of the concurrent unordered multimap <paramref name="_Umap"/>.</para>\r
722     /// </remarks>\r
723     /**/\r
724     concurrent_unordered_multimap(concurrent_unordered_multimap&& _Umap) : _Mybase(std::move(_Umap))\r
725     {\r
726     }\r
727 \r
728     /// <summary>\r
729     ///     Assigns the contents of another <c>concurrent_unordered_multimap</c> object to this one. This method is not concurrency-safe.\r
730     /// </summary>\r
731     /// <param name="_Umap">\r
732     ///     The source <c>concurrent_unordered_multimap</c> object.\r
733     /// </param>\r
734     /// <returns>\r
735     ///     A reference to this <c>concurrent_unordered_multimap</c> object.\r
736     /// </returns>\r
737     /// <remarks>\r
738     ///     After erasing any existing elements in a concurrent unordered multimap, <c>operator=</c> either copies or moves the contents of\r
739     ///     <paramref name="_Umap"/> into the concurrent unordered multimap.\r
740     /// </remarks>\r
741     /**/\r
742     concurrent_unordered_multimap& operator=(const concurrent_unordered_multimap& _Umap)\r
743     {\r
744         _Mybase::operator=(_Umap);\r
745         return (*this);\r
746     }\r
747 \r
748     /// <summary>\r
749     ///     Assigns the contents of another <c>concurrent_unordered_multimap</c> object to this one. This method is not concurrency-safe.\r
750     /// </summary>\r
751     /// <param name="_Umap">\r
752     ///     The source <c>concurrent_unordered_multimap</c> object.\r
753     /// </param>\r
754     /// <returns>\r
755     ///     A reference to this <c>concurrent_unordered_multimap</c> object.\r
756     /// </returns>\r
757     /// <remarks>\r
758     ///     After erasing any existing elements in a concurrent unordered multimap, <c>operator=</c> either copies or moves the contents of\r
759     ///     <paramref name="_Umap"/> into the concurrent unordered multimap.\r
760     /// </remarks>\r
761     /**/\r
762     concurrent_unordered_multimap& operator=(concurrent_unordered_multimap&& _Umap)\r
763     {\r
764         _Mybase::operator=(std::move(_Umap));\r
765         return (*this);\r
766     }\r
767 \r
768     // Modifiers\r
769     /// <summary>\r
770     ///     Inserts a value into the <c>concurrent_unordered_multimap</c> object. \r
771     /// </summary>\r
772     /// <param name="_Value">\r
773     ///     The value to be inserted into the <c>concurrent_unordered_multimap</c> object.\r
774     /// </param>\r
775     /// <remarks>\r
776     ///     The first function determines whether an element X exists in the sequence whose key has equivalent ordering to \r
777     ///     that of _Value. If not, it creates such an element X and initializes it with _Value. The function then determines the \r
778     ///     iterator where that designates X. If an insertion occurred, the function returns std::pair(where, true). Otherwise, \r
779     ///     it returns std::pair(where, false).\r
780     ///     <para>The second function uses the <c>const_iterator _Where</c> as a starting location to search for an insertion point</para>\r
781     ///     <para>The third function inserts the sequence of element values, from the range [_First, _Last).</para>\r
782     ///     <para>The last two functions behave the same as the first two, except that <paramref name="_Value"/> is used to construct the inserted value.</para>\r
783     /// </remarks>\r
784     /// <returns>\r
785     ///     An iterator pointing to the insertion location.\r
786     /// </returns>\r
787     /**/\r
788     iterator insert(const value_type& _Value)\r
789     {\r
790         return (_Mybase::insert(_Value)).first;\r
791     }\r
792 \r
793     /// <summary>\r
794     ///     Inserts a value into the <c>concurrent_unordered_multimap</c> object. \r
795     /// </summary>\r
796     /// <param name="_Where">\r
797     ///     The starting location to search for an insertion point into the <c>concurrent_unordered_multimap</c> object.\r
798     /// </param>\r
799     /// <param name="_Value">\r
800     ///     The value to be inserted into the <c>concurrent_unordered_multimap</c> object.\r
801     /// </param>\r
802     /// <remarks>\r
803     ///     The first function determines whether an element X exists in the sequence whose key has equivalent ordering to \r
804     ///     that of _Value. If not, it creates such an element X and initializes it with _Value. The function then determines the \r
805     ///     iterator where that designates X. If an insertion occurred, the function returns std::pair(where, true). Otherwise, \r
806     ///     it returns std::pair(where, false).\r
807     ///     <para>The second function uses the <c>const_iterator _Where</c> as a starting location to search for an insertion point</para>\r
808     ///     <para>The third function inserts the sequence of element values, from the range [_First, _Last).</para>\r
809     ///     <para>The last two functions behave the same as the first two, except that <paramref name="_Value"/> is used to construct the inserted value.</para>\r
810     /// </remarks>\r
811     /// <returns>\r
812     ///     The iterator for the <c>concurrent_unordered_multimap</c> object.\r
813     /// </returns>\r
814     iterator insert(const_iterator _Where, const value_type& _Value)\r
815     {\r
816         return _Mybase::insert(_Where, _Value);\r
817     }\r
818 \r
819     /// <summary>\r
820     ///     Inserts values into the <c>concurrent_unordered_multimap</c> object. \r
821     /// </summary>\r
822     /// <typeparam name="_Iterator">\r
823     ///     The iterator type used for insertion.\r
824     /// </typeparm>\r
825     /// <param name="_First">\r
826     ///     The starting location in an itertor of elements to insert into the <c>concurrent_unordered_multimap</c> object.\r
827     /// </param>\r
828     /// <param name="_Last">\r
829     ///     The ending location in an itertor of elements to insert into the <c>concurrent_unordered_multimap</c> object.\r
830     /// </param>\r
831     /// <remarks>\r
832     ///     The first function determines whether an element X exists in the sequence whose key has equivalent ordering to \r
833     ///     that of _Value. If not, it creates such an element X and initializes it with _Value. The function then determines the \r
834     ///     iterator where that designates X. If an insertion occurred, the function returns std::pair(where, true). Otherwise, \r
835     ///     it returns std::pair(where, false).\r
836     ///     <para>The second function uses the <c>const_iterator _Where</c> as a starting location to search for an insertion point</para>\r
837     ///     <para>The third function inserts the sequence of element values, from the range [_First, _Last).</para>\r
838     ///     <para>The last two functions behave the same as the first two, except that <paramref name="_Value"/> is used to construct the inserted value.</para>\r
839     /// </remarks>\r
840     template<class _Iterator>\r
841     void insert(_Iterator _First, _Iterator _Last)\r
842     {\r
843         _Mybase::insert(_First, _Last);\r
844     }\r
845 \r
846     /// <summary>\r
847     ///     Inserts a value into the <c>concurrent_unordered_multimap</c> object. \r
848     /// </summary>\r
849     /// <typeparam name="_Valty">\r
850     ///     The type of the value inserted into the map.\r
851     /// </typeparm>\r
852     /// <param name="_Value">\r
853     ///     The value to be inserted into the <c>concurrent_unordered_multimap</c> object.\r
854     /// </param>\r
855     /// <remarks>\r
856     ///     The first function determines whether an element X exists in the sequence whose key has equivalent ordering to \r
857     ///     that of _Value. If not, it creates such an element X and initializes it with _Value. The function then determines the \r
858     ///     iterator where that designates X. If an insertion occurred, the function returns std::pair(where, true). Otherwise, \r
859     ///     it returns std::pair(where, false).\r
860     ///     <para>The second function uses the <c>const_iterator _Where</c> as a starting location to search for an insertion point</para>\r
861     ///     <para>The third function inserts the sequence of element values, from the range [_First, _Last).</para>\r
862     ///     <para>The last two functions behave the same as the first two, except that <paramref name="_Value"/> is used to construct the inserted value.</para>\r
863     /// </remarks>\r
864     /// <returns>\r
865     ///     An iterator pointing to the insertion location.\r
866     /// </returns>\r
867     /**/\r
868     template<class _Valty>\r
869     iterator insert(_Valty&& _Value)\r
870     {\r
871         return (_Mybase::insert(std::forward<_Valty>(_Value))).first;\r
872     }\r
873 \r
874     /// <summary>\r
875     ///     Inserts a value into the <c>concurrent_unordered_multimap</c> object. \r
876     /// </summary>\r
877     /// <typeparam name="_Valty">\r
878     ///     The type of the value inserted into the map.\r
879     /// </typeparm>\r
880     /// <param name="_Where">\r
881     ///     The starting location to search for an insertion point into the <c>concurrent_unordered_multimap</c> object.\r
882     /// </param>\r
883     /// <param name="_Value">\r
884     ///     The value to be inserted into the <c>concurrent_unordered_multimap</c> object.\r
885     /// </param>\r
886     /// <remarks>\r
887     ///     The first function determines whether an element X exists in the sequence whose key has equivalent ordering to \r
888     ///     that of _Value. If not, it creates such an element X and initializes it with _Value. The function then determines the \r
889     ///     iterator where that designates X. If an insertion occurred, the function returns std::pair(where, true). Otherwise, \r
890     ///     it returns std::pair(where, false).\r
891     ///     <para>The second function uses the <c>const_iterator _Where</c> as a starting location to search for an insertion point</para>\r
892     ///     <para>The third function inserts the sequence of element values, from the range [_First, _Last).</para>\r
893     ///     <para>The last two functions behave the same as the first two, except that <paramref name="_Value"/> is used to construct the inserted value.</para>\r
894     /// </remarks>\r
895     /// <returns>\r
896     ///     The iterator for the <c>concurrent_unordered_multimap</c> object.\r
897     /// </returns>\r
898     template<class _Valty>\r
899         typename std::tr1::enable_if<!std::tr1::is_same<const_iterator, \r
900             typename std::tr1::remove_reference<_Valty>::type>::value, iterator>::type\r
901     insert(const_iterator _Where, _Valty&& _Value)\r
902     {\r
903         return _Mybase::insert(_Where, std::forward<_Valty>(_Value));\r
904     }\r
905 \r
906     /// <summary>\r
907     ///     Erases elements from the <c>concurrent_unordered_multimap</c>. This method is not concurrency-safe.\r
908     /// </summary>\r
909     /// <param name="_Where">\r
910     ///     The iterator position to erase from.\r
911     /// </param>\r
912     /// <remarks>\r
913     ///     The first function erases an element from the map given an iterator position.\r
914     ///     <para>The second function erases an element matching a key</para>\r
915     ///     <para>The third function erases elements given an iterator begin and end position</para>\r
916     /// </remarks>\r
917     /// <returns>\r
918     ///     The iterator for this <c>concurrent_unordered_multimap</c> object.\r
919     /// </returns>\r
920     /**/\r
921     iterator unsafe_erase(const_iterator _Where)\r
922     {\r
923         return _Mybase::unsafe_erase(_Where);\r
924     }\r
925 \r
926     /// <summary>\r
927     ///     Erases elements from the <c>concurrent_unordered_multimap</c>. This method is not concurrency-safe.\r
928     /// </summary>\r
929     /// <param name="_Keyval">\r
930     ///     The key to erase.\r
931     /// </param>\r
932     /// <remarks>\r
933     ///     The first function erases an element from the map given an iterator position.\r
934     ///     <para>The second function erases an element matching a key</para>\r
935     ///     <para>The third function erases elements given an iterator begin and end position</para>\r
936     /// </remarks>\r
937     /// <returns>\r
938     ///     The count of elements erased from this <c>concurrent_unordered_multimap</c> object.\r
939     /// </returns>\r
940     /**/\r
941     size_type unsafe_erase(const key_type& _Keyval)\r
942     {\r
943         return _Mybase::unsafe_erase(_Keyval);\r
944     }\r
945 \r
946     /// <summary>\r
947     ///     Erases elements from the <c>concurrent_unordered_multimap</c>. This method is not concurrency-safe.\r
948     /// </summary>\r
949     /// <param name="_Begin">\r
950     ///     Position of the first element in the range of elements to be erased.\r
951     /// </param>\r
952     /// <param name="_End">\r
953     ///     Position of the first element beyond the range of elements to be erased.\r
954     /// </param>\r
955     /// <remarks>\r
956     ///     The first function erases an element from the map given an iterator position.\r
957     ///     <para>The second function erases an element matching a key</para>\r
958     ///     <para>The third function erases elements given an iterator begin and end position</para>\r
959     /// </remarks>\r
960     /// <returns>\r
961     ///     The iterator for this <c>concurrent_unordered_multimap</c> object.\r
962     /// </returns>\r
963     /**/\r
964     iterator unsafe_erase(const_iterator _First, const_iterator _Last)\r
965     {\r
966         return _Mybase::unsafe_erase(_First, _Last);\r
967     }\r
968 \r
969     /// <summary>\r
970     ///     Swaps the contents of two <c>concurrent_unordered_multimap</c> objects. \r
971     ///     This method is not concurrency-safe.\r
972     /// </summary>\r
973     /// <param name="_Umap">\r
974     ///     The <c>concurrent_unordered_multimap</c> object to swap with.\r
975     /// </param>\r
976     /**/\r
977     void swap(concurrent_unordered_multimap& _Umap)\r
978     {\r
979         _Mybase::swap(_Umap);\r
980     }\r
981 \r
982     // Observers\r
983     /// <summary>\r
984     ///     The hash function object.\r
985     /// </summary>\r
986     /**/\r
987     hasher hash_function() const\r
988     {\r
989         return _M_comparator._M_hash_object;\r
990     }\r
991 \r
992     /// <summary>\r
993     ///     The equality comparison function object.\r
994     /// </summary>\r
995     /**/\r
996     key_equal key_eq() const\r
997     {\r
998         return _M_comparator._M_key_compare_object;\r
999     }\r
1000 };\r
1001 } // namespace Concurrency\r
1002 \r
1003 #pragma pack(pop)\r