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