Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/unordered/detail/buckets.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 | |
2 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. | |
3 // Copyright (C) 2005-2011 Daniel James | |
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | |
7 #ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED | |
8 #define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED | |
9 | |
10 #if defined(_MSC_VER) && (_MSC_VER >= 1020) | |
11 # pragma once | |
12 #endif | |
13 | |
14 #include <boost/unordered/detail/util.hpp> | |
15 #include <boost/unordered/detail/allocate.hpp> | |
16 #include <boost/type_traits/aligned_storage.hpp> | |
17 #include <boost/type_traits/alignment_of.hpp> | |
18 #include <boost/type_traits/is_nothrow_move_constructible.hpp> | |
19 #include <boost/type_traits/is_nothrow_move_assignable.hpp> | |
20 #include <boost/swap.hpp> | |
21 #include <boost/assert.hpp> | |
22 #include <boost/limits.hpp> | |
23 #include <boost/iterator.hpp> | |
24 | |
25 namespace boost { namespace unordered { namespace detail { | |
26 | |
27 template <typename Types> struct table; | |
28 template <typename NodePointer> struct bucket; | |
29 struct ptr_bucket; | |
30 template <typename Types> struct table_impl; | |
31 template <typename Types> struct grouped_table_impl; | |
32 | |
33 }}} | |
34 | |
35 // The 'iterator_detail' namespace was a misguided attempt at avoiding ADL | |
36 // in the detail namespace. It didn't work because the template parameters | |
37 // were in detail. I'm not changing it at the moment to be safe. I might | |
38 // do in the future if I change the iterator types. | |
39 namespace boost { namespace unordered { namespace iterator_detail { | |
40 | |
41 //////////////////////////////////////////////////////////////////////////// | |
42 // Iterators | |
43 // | |
44 // all no throw | |
45 | |
46 template <typename Node> struct iterator; | |
47 template <typename Node, typename ConstNodePointer> struct c_iterator; | |
48 template <typename Node, typename Policy> struct l_iterator; | |
49 template <typename Node, typename ConstNodePointer, typename Policy> | |
50 struct cl_iterator; | |
51 | |
52 // Local Iterators | |
53 // | |
54 // all no throw | |
55 | |
56 template <typename Node, typename Policy> | |
57 struct l_iterator | |
58 : public boost::iterator< | |
59 std::forward_iterator_tag, | |
60 typename Node::value_type, | |
61 std::ptrdiff_t, | |
62 typename Node::node_pointer, | |
63 typename Node::value_type&> | |
64 { | |
65 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) | |
66 template <typename Node2, typename ConstNodePointer, typename Policy2> | |
67 friend struct boost::unordered::iterator_detail::cl_iterator; | |
68 private: | |
69 #endif | |
70 typedef typename Node::node_pointer node_pointer; | |
71 typedef boost::unordered::iterator_detail::iterator<Node> iterator; | |
72 node_pointer ptr_; | |
73 std::size_t bucket_; | |
74 std::size_t bucket_count_; | |
75 | |
76 public: | |
77 | |
78 typedef typename Node::value_type value_type; | |
79 | |
80 l_iterator() BOOST_NOEXCEPT : ptr_() {} | |
81 | |
82 l_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT | |
83 : ptr_(x.node_), bucket_(b), bucket_count_(c) {} | |
84 | |
85 value_type& operator*() const { | |
86 return ptr_->value(); | |
87 } | |
88 | |
89 value_type* operator->() const { | |
90 return ptr_->value_ptr(); | |
91 } | |
92 | |
93 l_iterator& operator++() { | |
94 ptr_ = static_cast<node_pointer>(ptr_->next_); | |
95 if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) | |
96 != bucket_) | |
97 ptr_ = node_pointer(); | |
98 return *this; | |
99 } | |
100 | |
101 l_iterator operator++(int) { | |
102 l_iterator tmp(*this); | |
103 ++(*this); | |
104 return tmp; | |
105 } | |
106 | |
107 bool operator==(l_iterator x) const BOOST_NOEXCEPT { | |
108 return ptr_ == x.ptr_; | |
109 } | |
110 | |
111 bool operator!=(l_iterator x) const BOOST_NOEXCEPT { | |
112 return ptr_ != x.ptr_; | |
113 } | |
114 }; | |
115 | |
116 template <typename Node, typename ConstNodePointer, typename Policy> | |
117 struct cl_iterator | |
118 : public boost::iterator< | |
119 std::forward_iterator_tag, | |
120 typename Node::value_type, | |
121 std::ptrdiff_t, | |
122 ConstNodePointer, | |
123 typename Node::value_type const&> | |
124 { | |
125 friend struct boost::unordered::iterator_detail::l_iterator | |
126 <Node, Policy>; | |
127 private: | |
128 | |
129 typedef typename Node::node_pointer node_pointer; | |
130 typedef boost::unordered::iterator_detail::iterator<Node> iterator; | |
131 node_pointer ptr_; | |
132 std::size_t bucket_; | |
133 std::size_t bucket_count_; | |
134 | |
135 public: | |
136 | |
137 typedef typename Node::value_type value_type; | |
138 | |
139 cl_iterator() BOOST_NOEXCEPT : ptr_() {} | |
140 | |
141 cl_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT : | |
142 ptr_(x.node_), bucket_(b), bucket_count_(c) {} | |
143 | |
144 cl_iterator(boost::unordered::iterator_detail::l_iterator< | |
145 Node, Policy> const& x) BOOST_NOEXCEPT : | |
146 ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_) | |
147 {} | |
148 | |
149 value_type const& operator*() const { | |
150 return ptr_->value(); | |
151 } | |
152 | |
153 value_type const* operator->() const { | |
154 return ptr_->value_ptr(); | |
155 } | |
156 | |
157 cl_iterator& operator++() { | |
158 ptr_ = static_cast<node_pointer>(ptr_->next_); | |
159 if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) | |
160 != bucket_) | |
161 ptr_ = node_pointer(); | |
162 return *this; | |
163 } | |
164 | |
165 cl_iterator operator++(int) { | |
166 cl_iterator tmp(*this); | |
167 ++(*this); | |
168 return tmp; | |
169 } | |
170 | |
171 friend bool operator==(cl_iterator const& x, cl_iterator const& y) | |
172 BOOST_NOEXCEPT | |
173 { | |
174 return x.ptr_ == y.ptr_; | |
175 } | |
176 | |
177 friend bool operator!=(cl_iterator const& x, cl_iterator const& y) | |
178 BOOST_NOEXCEPT | |
179 { | |
180 return x.ptr_ != y.ptr_; | |
181 } | |
182 }; | |
183 | |
184 template <typename Node> | |
185 struct iterator | |
186 : public boost::iterator< | |
187 std::forward_iterator_tag, | |
188 typename Node::value_type, | |
189 std::ptrdiff_t, | |
190 typename Node::node_pointer, | |
191 typename Node::value_type&> | |
192 { | |
193 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) | |
194 template <typename, typename> | |
195 friend struct boost::unordered::iterator_detail::c_iterator; | |
196 template <typename, typename> | |
197 friend struct boost::unordered::iterator_detail::l_iterator; | |
198 template <typename, typename, typename> | |
199 friend struct boost::unordered::iterator_detail::cl_iterator; | |
200 template <typename> | |
201 friend struct boost::unordered::detail::table; | |
202 template <typename> | |
203 friend struct boost::unordered::detail::table_impl; | |
204 template <typename> | |
205 friend struct boost::unordered::detail::grouped_table_impl; | |
206 private: | |
207 #endif | |
208 typedef typename Node::node_pointer node_pointer; | |
209 node_pointer node_; | |
210 | |
211 public: | |
212 | |
213 typedef typename Node::value_type value_type; | |
214 | |
215 iterator() BOOST_NOEXCEPT : node_() {} | |
216 | |
217 explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT : | |
218 node_(static_cast<node_pointer>(x)) {} | |
219 | |
220 value_type& operator*() const { | |
221 return node_->value(); | |
222 } | |
223 | |
224 value_type* operator->() const { | |
225 return &node_->value(); | |
226 } | |
227 | |
228 iterator& operator++() { | |
229 node_ = static_cast<node_pointer>(node_->next_); | |
230 return *this; | |
231 } | |
232 | |
233 iterator operator++(int) { | |
234 iterator tmp(node_); | |
235 node_ = static_cast<node_pointer>(node_->next_); | |
236 return tmp; | |
237 } | |
238 | |
239 bool operator==(iterator const& x) const BOOST_NOEXCEPT { | |
240 return node_ == x.node_; | |
241 } | |
242 | |
243 bool operator!=(iterator const& x) const BOOST_NOEXCEPT { | |
244 return node_ != x.node_; | |
245 } | |
246 }; | |
247 | |
248 template <typename Node, typename ConstNodePointer> | |
249 struct c_iterator | |
250 : public boost::iterator< | |
251 std::forward_iterator_tag, | |
252 typename Node::value_type, | |
253 std::ptrdiff_t, | |
254 ConstNodePointer, | |
255 typename Node::value_type const&> | |
256 { | |
257 friend struct boost::unordered::iterator_detail::iterator<Node>; | |
258 | |
259 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) | |
260 template <typename> | |
261 friend struct boost::unordered::detail::table; | |
262 template <typename> | |
263 friend struct boost::unordered::detail::table_impl; | |
264 template <typename> | |
265 friend struct boost::unordered::detail::grouped_table_impl; | |
266 | |
267 private: | |
268 #endif | |
269 typedef typename Node::node_pointer node_pointer; | |
270 typedef boost::unordered::iterator_detail::iterator<Node> iterator; | |
271 node_pointer node_; | |
272 | |
273 public: | |
274 | |
275 typedef typename Node::value_type value_type; | |
276 | |
277 c_iterator() BOOST_NOEXCEPT : node_() {} | |
278 | |
279 explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT : | |
280 node_(static_cast<node_pointer>(x)) {} | |
281 | |
282 c_iterator(iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {} | |
283 | |
284 value_type const& operator*() const { | |
285 return node_->value(); | |
286 } | |
287 | |
288 value_type const* operator->() const { | |
289 return &node_->value(); | |
290 } | |
291 | |
292 c_iterator& operator++() { | |
293 node_ = static_cast<node_pointer>(node_->next_); | |
294 return *this; | |
295 } | |
296 | |
297 c_iterator operator++(int) { | |
298 c_iterator tmp(node_); | |
299 node_ = static_cast<node_pointer>(node_->next_); | |
300 return tmp; | |
301 } | |
302 | |
303 friend bool operator==(c_iterator const& x, c_iterator const& y) | |
304 BOOST_NOEXCEPT | |
305 { | |
306 return x.node_ == y.node_; | |
307 } | |
308 | |
309 friend bool operator!=(c_iterator const& x, c_iterator const& y) | |
310 BOOST_NOEXCEPT | |
311 { | |
312 return x.node_ != y.node_; | |
313 } | |
314 }; | |
315 }}} | |
316 | |
317 namespace boost { namespace unordered { namespace detail { | |
318 | |
319 /////////////////////////////////////////////////////////////////// | |
320 // | |
321 // Node construction | |
322 | |
323 template <typename NodeAlloc> | |
324 struct node_constructor | |
325 { | |
326 private: | |
327 | |
328 typedef NodeAlloc node_allocator; | |
329 typedef boost::unordered::detail::allocator_traits<NodeAlloc> | |
330 node_allocator_traits; | |
331 typedef typename node_allocator_traits::value_type node; | |
332 typedef typename node_allocator_traits::pointer node_pointer; | |
333 typedef typename node::value_type value_type; | |
334 | |
335 protected: | |
336 | |
337 node_allocator& alloc_; | |
338 node_pointer node_; | |
339 bool node_constructed_; | |
340 bool value_constructed_; | |
341 | |
342 public: | |
343 | |
344 node_constructor(node_allocator& n) : | |
345 alloc_(n), | |
346 node_(), | |
347 node_constructed_(false), | |
348 value_constructed_(false) | |
349 { | |
350 } | |
351 | |
352 ~node_constructor(); | |
353 | |
354 void construct(); | |
355 | |
356 template <BOOST_UNORDERED_EMPLACE_TEMPLATE> | |
357 void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS) | |
358 { | |
359 construct(); | |
360 boost::unordered::detail::func::construct_value_impl( | |
361 alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD); | |
362 value_constructed_ = true; | |
363 } | |
364 | |
365 template <typename A0> | |
366 void construct_with_value2(BOOST_FWD_REF(A0) a0) | |
367 { | |
368 construct(); | |
369 boost::unordered::detail::func::construct_value_impl( | |
370 alloc_, node_->value_ptr(), | |
371 BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0))); | |
372 value_constructed_ = true; | |
373 } | |
374 | |
375 value_type const& value() const { | |
376 BOOST_ASSERT(node_ && node_constructed_ && value_constructed_); | |
377 return node_->value(); | |
378 } | |
379 | |
380 // no throw | |
381 node_pointer release() | |
382 { | |
383 BOOST_ASSERT(node_ && node_constructed_); | |
384 node_pointer p = node_; | |
385 node_ = node_pointer(); | |
386 return p; | |
387 } | |
388 | |
389 private: | |
390 node_constructor(node_constructor const&); | |
391 node_constructor& operator=(node_constructor const&); | |
392 }; | |
393 | |
394 template <typename Alloc> | |
395 node_constructor<Alloc>::~node_constructor() | |
396 { | |
397 if (node_) { | |
398 if (value_constructed_) { | |
399 boost::unordered::detail::func::destroy_value_impl(alloc_, | |
400 node_->value_ptr()); | |
401 } | |
402 | |
403 if (node_constructed_) { | |
404 node_allocator_traits::destroy(alloc_, | |
405 boost::addressof(*node_)); | |
406 } | |
407 | |
408 node_allocator_traits::deallocate(alloc_, node_, 1); | |
409 } | |
410 } | |
411 | |
412 template <typename Alloc> | |
413 void node_constructor<Alloc>::construct() | |
414 { | |
415 if(!node_) { | |
416 node_constructed_ = false; | |
417 value_constructed_ = false; | |
418 | |
419 node_ = node_allocator_traits::allocate(alloc_, 1); | |
420 | |
421 node_allocator_traits::construct(alloc_, | |
422 boost::addressof(*node_), node()); | |
423 node_->init(node_); | |
424 node_constructed_ = true; | |
425 } | |
426 else { | |
427 BOOST_ASSERT(node_constructed_); | |
428 | |
429 if (value_constructed_) | |
430 { | |
431 boost::unordered::detail::func::destroy_value_impl(alloc_, | |
432 node_->value_ptr()); | |
433 value_constructed_ = false; | |
434 } | |
435 } | |
436 } | |
437 | |
438 /////////////////////////////////////////////////////////////////// | |
439 // | |
440 // Node Holder | |
441 // | |
442 // Temporary store for nodes. Deletes any that aren't used. | |
443 | |
444 template <typename NodeAlloc> | |
445 struct node_holder : private node_constructor<NodeAlloc> | |
446 { | |
447 private: | |
448 typedef node_constructor<NodeAlloc> base; | |
449 | |
450 typedef NodeAlloc node_allocator; | |
451 typedef boost::unordered::detail::allocator_traits<NodeAlloc> | |
452 node_allocator_traits; | |
453 typedef typename node_allocator_traits::value_type node; | |
454 typedef typename node_allocator_traits::pointer node_pointer; | |
455 typedef typename node::value_type value_type; | |
456 typedef typename node::link_pointer link_pointer; | |
457 typedef boost::unordered::iterator_detail::iterator<node> iterator; | |
458 | |
459 node_pointer nodes_; | |
460 | |
461 public: | |
462 | |
463 template <typename Table> | |
464 explicit node_holder(Table& b) : | |
465 base(b.node_alloc()), | |
466 nodes_() | |
467 { | |
468 if (b.size_) { | |
469 typename Table::link_pointer prev = b.get_previous_start(); | |
470 nodes_ = static_cast<node_pointer>(prev->next_); | |
471 prev->next_ = link_pointer(); | |
472 b.size_ = 0; | |
473 } | |
474 } | |
475 | |
476 ~node_holder(); | |
477 | |
478 void node_for_assignment() | |
479 { | |
480 if (!this->node_ && nodes_) { | |
481 this->node_ = nodes_; | |
482 nodes_ = static_cast<node_pointer>(nodes_->next_); | |
483 this->node_->init(this->node_); | |
484 this->node_->next_ = link_pointer(); | |
485 | |
486 this->node_constructed_ = true; | |
487 this->value_constructed_ = true; | |
488 } | |
489 } | |
490 | |
491 template <typename T> | |
492 inline void assign_impl(T const& v) { | |
493 if (this->node_ && this->value_constructed_) { | |
494 this->node_->value() = v; | |
495 } | |
496 else { | |
497 this->construct_with_value2(v); | |
498 } | |
499 } | |
500 | |
501 template <typename T1, typename T2> | |
502 inline void assign_impl(std::pair<T1 const, T2> const& v) { | |
503 this->construct_with_value2(v); | |
504 } | |
505 | |
506 template <typename T> | |
507 inline void move_assign_impl(T& v) { | |
508 if (this->node_ && this->value_constructed_) { | |
509 this->node_->value() = boost::move(v); | |
510 } | |
511 else { | |
512 this->construct_with_value2(boost::move(v)); | |
513 } | |
514 } | |
515 | |
516 template <typename T1, typename T2> | |
517 inline void move_assign_impl(std::pair<T1 const, T2>& v) { | |
518 this->construct_with_value2(boost::move(v)); | |
519 } | |
520 | |
521 node_pointer copy_of(value_type const& v) | |
522 { | |
523 node_for_assignment(); | |
524 assign_impl(v); | |
525 return base::release(); | |
526 } | |
527 | |
528 node_pointer move_copy_of(value_type& v) | |
529 { | |
530 node_for_assignment(); | |
531 move_assign_impl(v); | |
532 return base::release(); | |
533 } | |
534 | |
535 iterator begin() const | |
536 { | |
537 return iterator(nodes_); | |
538 } | |
539 }; | |
540 | |
541 template <typename Alloc> | |
542 node_holder<Alloc>::~node_holder() | |
543 { | |
544 while (nodes_) { | |
545 node_pointer p = nodes_; | |
546 nodes_ = static_cast<node_pointer>(p->next_); | |
547 | |
548 boost::unordered::detail::func::destroy_value_impl(this->alloc_, | |
549 p->value_ptr()); | |
550 node_allocator_traits::destroy(this->alloc_, boost::addressof(*p)); | |
551 node_allocator_traits::deallocate(this->alloc_, p, 1); | |
552 } | |
553 } | |
554 | |
555 /////////////////////////////////////////////////////////////////// | |
556 // | |
557 // Bucket | |
558 | |
559 template <typename NodePointer> | |
560 struct bucket | |
561 { | |
562 typedef NodePointer link_pointer; | |
563 link_pointer next_; | |
564 | |
565 bucket() : next_() {} | |
566 | |
567 link_pointer first_from_start() | |
568 { | |
569 return next_; | |
570 } | |
571 | |
572 enum { extra_node = true }; | |
573 }; | |
574 | |
575 struct ptr_bucket | |
576 { | |
577 typedef ptr_bucket* link_pointer; | |
578 link_pointer next_; | |
579 | |
580 ptr_bucket() : next_(0) {} | |
581 | |
582 link_pointer first_from_start() | |
583 { | |
584 return this; | |
585 } | |
586 | |
587 enum { extra_node = false }; | |
588 }; | |
589 | |
590 /////////////////////////////////////////////////////////////////// | |
591 // | |
592 // Hash Policy | |
593 | |
594 template <typename SizeT> | |
595 struct prime_policy | |
596 { | |
597 template <typename Hash, typename T> | |
598 static inline SizeT apply_hash(Hash const& hf, T const& x) { | |
599 return hf(x); | |
600 } | |
601 | |
602 static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) { | |
603 return hash % bucket_count; | |
604 } | |
605 | |
606 static inline SizeT new_bucket_count(SizeT min) { | |
607 return boost::unordered::detail::next_prime(min); | |
608 } | |
609 | |
610 static inline SizeT prev_bucket_count(SizeT max) { | |
611 return boost::unordered::detail::prev_prime(max); | |
612 } | |
613 }; | |
614 | |
615 template <typename SizeT> | |
616 struct mix64_policy | |
617 { | |
618 template <typename Hash, typename T> | |
619 static inline SizeT apply_hash(Hash const& hf, T const& x) { | |
620 SizeT key = hf(x); | |
621 key = (~key) + (key << 21); // key = (key << 21) - key - 1; | |
622 key = key ^ (key >> 24); | |
623 key = (key + (key << 3)) + (key << 8); // key * 265 | |
624 key = key ^ (key >> 14); | |
625 key = (key + (key << 2)) + (key << 4); // key * 21 | |
626 key = key ^ (key >> 28); | |
627 key = key + (key << 31); | |
628 return key; | |
629 } | |
630 | |
631 static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) { | |
632 return hash & (bucket_count - 1); | |
633 } | |
634 | |
635 static inline SizeT new_bucket_count(SizeT min) { | |
636 if (min <= 4) return 4; | |
637 --min; | |
638 min |= min >> 1; | |
639 min |= min >> 2; | |
640 min |= min >> 4; | |
641 min |= min >> 8; | |
642 min |= min >> 16; | |
643 min |= min >> 32; | |
644 return min + 1; | |
645 } | |
646 | |
647 static inline SizeT prev_bucket_count(SizeT max) { | |
648 max |= max >> 1; | |
649 max |= max >> 2; | |
650 max |= max >> 4; | |
651 max |= max >> 8; | |
652 max |= max >> 16; | |
653 max |= max >> 32; | |
654 return (max >> 1) + 1; | |
655 } | |
656 }; | |
657 | |
658 template <int digits, int radix> | |
659 struct pick_policy_impl { | |
660 typedef prime_policy<std::size_t> type; | |
661 }; | |
662 | |
663 template <> | |
664 struct pick_policy_impl<64, 2> { | |
665 typedef mix64_policy<std::size_t> type; | |
666 }; | |
667 | |
668 struct pick_policy : | |
669 pick_policy_impl< | |
670 std::numeric_limits<std::size_t>::digits, | |
671 std::numeric_limits<std::size_t>::radix> {}; | |
672 | |
673 //////////////////////////////////////////////////////////////////////////// | |
674 // Functions | |
675 | |
676 // Assigning and swapping the equality and hash function objects | |
677 // needs strong exception safety. To implement that normally we'd | |
678 // require one of them to be known to not throw and the other to | |
679 // guarantee strong exception safety. Unfortunately they both only | |
680 // have basic exception safety. So to acheive strong exception | |
681 // safety we have storage space for two copies, and assign the new | |
682 // copies to the unused space. Then switch to using that to use | |
683 // them. This is implemented in 'set_hash_functions' which | |
684 // atomically assigns the new function objects in a strongly | |
685 // exception safe manner. | |
686 | |
687 template <class H, class P, bool NoThrowMoveAssign> | |
688 class set_hash_functions; | |
689 | |
690 template <class H, class P> | |
691 class functions | |
692 { | |
693 public: | |
694 static const bool nothrow_move_assignable = | |
695 boost::is_nothrow_move_assignable<H>::value && | |
696 boost::is_nothrow_move_assignable<P>::value; | |
697 static const bool nothrow_move_constructible = | |
698 boost::is_nothrow_move_constructible<H>::value && | |
699 boost::is_nothrow_move_constructible<P>::value; | |
700 | |
701 private: | |
702 friend class boost::unordered::detail::set_hash_functions<H, P, | |
703 nothrow_move_assignable>; | |
704 functions& operator=(functions const&); | |
705 | |
706 typedef compressed<H, P> function_pair; | |
707 | |
708 typedef typename boost::aligned_storage< | |
709 sizeof(function_pair), | |
710 boost::alignment_of<function_pair>::value>::type aligned_function; | |
711 | |
712 bool current_; // The currently active functions. | |
713 aligned_function funcs_[2]; | |
714 | |
715 function_pair const& current() const { | |
716 return *static_cast<function_pair const*>( | |
717 static_cast<void const*>(&funcs_[current_])); | |
718 } | |
719 | |
720 function_pair& current() { | |
721 return *static_cast<function_pair*>( | |
722 static_cast<void*>(&funcs_[current_])); | |
723 } | |
724 | |
725 void construct(bool which, H const& hf, P const& eq) | |
726 { | |
727 new((void*) &funcs_[which]) function_pair(hf, eq); | |
728 } | |
729 | |
730 void construct(bool which, function_pair const& f, | |
731 boost::unordered::detail::false_type = | |
732 boost::unordered::detail::false_type()) | |
733 { | |
734 new((void*) &funcs_[which]) function_pair(f); | |
735 } | |
736 | |
737 void construct(bool which, function_pair& f, | |
738 boost::unordered::detail::true_type) | |
739 { | |
740 new((void*) &funcs_[which]) function_pair(f, | |
741 boost::unordered::detail::move_tag()); | |
742 } | |
743 | |
744 void destroy(bool which) | |
745 { | |
746 boost::unordered::detail::func::destroy((function_pair*)(&funcs_[which])); | |
747 } | |
748 | |
749 public: | |
750 | |
751 typedef boost::unordered::detail::set_hash_functions<H, P, | |
752 nothrow_move_assignable> set_hash_functions; | |
753 | |
754 functions(H const& hf, P const& eq) | |
755 : current_(false) | |
756 { | |
757 construct(current_, hf, eq); | |
758 } | |
759 | |
760 functions(functions const& bf) | |
761 : current_(false) | |
762 { | |
763 construct(current_, bf.current()); | |
764 } | |
765 | |
766 functions(functions& bf, boost::unordered::detail::move_tag) | |
767 : current_(false) | |
768 { | |
769 construct(current_, bf.current(), | |
770 boost::unordered::detail::integral_constant<bool, | |
771 nothrow_move_constructible>()); | |
772 } | |
773 | |
774 ~functions() { | |
775 this->destroy(current_); | |
776 } | |
777 | |
778 H const& hash_function() const { | |
779 return current().first(); | |
780 } | |
781 | |
782 P const& key_eq() const { | |
783 return current().second(); | |
784 } | |
785 }; | |
786 | |
787 template <class H, class P> | |
788 class set_hash_functions<H, P, false> | |
789 { | |
790 set_hash_functions(set_hash_functions const&); | |
791 set_hash_functions& operator=(set_hash_functions const&); | |
792 | |
793 typedef functions<H, P> functions_type; | |
794 | |
795 functions_type& functions_; | |
796 bool tmp_functions_; | |
797 | |
798 public: | |
799 | |
800 set_hash_functions(functions_type& f, H const& h, P const& p) | |
801 : functions_(f), | |
802 tmp_functions_(!f.current_) | |
803 { | |
804 f.construct(tmp_functions_, h, p); | |
805 } | |
806 | |
807 set_hash_functions(functions_type& f, functions_type const& other) | |
808 : functions_(f), | |
809 tmp_functions_(!f.current_) | |
810 { | |
811 f.construct(tmp_functions_, other.current()); | |
812 } | |
813 | |
814 ~set_hash_functions() | |
815 { | |
816 functions_.destroy(tmp_functions_); | |
817 } | |
818 | |
819 void commit() | |
820 { | |
821 functions_.current_ = tmp_functions_; | |
822 tmp_functions_ = !tmp_functions_; | |
823 } | |
824 }; | |
825 | |
826 template <class H, class P> | |
827 class set_hash_functions<H, P, true> | |
828 { | |
829 set_hash_functions(set_hash_functions const&); | |
830 set_hash_functions& operator=(set_hash_functions const&); | |
831 | |
832 typedef functions<H, P> functions_type; | |
833 | |
834 functions_type& functions_; | |
835 H hash_; | |
836 P pred_; | |
837 | |
838 public: | |
839 | |
840 set_hash_functions(functions_type& f, H const& h, P const& p) : | |
841 functions_(f), | |
842 hash_(h), | |
843 pred_(p) {} | |
844 | |
845 set_hash_functions(functions_type& f, functions_type const& other) : | |
846 functions_(f), | |
847 hash_(other.hash_function()), | |
848 pred_(other.key_eq()) {} | |
849 | |
850 void commit() | |
851 { | |
852 functions_.current().first() = boost::move(hash_); | |
853 functions_.current().second() = boost::move(pred_); | |
854 } | |
855 }; | |
856 | |
857 //////////////////////////////////////////////////////////////////////////// | |
858 // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter | |
859 // e.g. for int | |
860 | |
861 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
862 # define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T) | |
863 #else | |
864 struct please_ignore_this_overload { | |
865 typedef please_ignore_this_overload type; | |
866 }; | |
867 | |
868 template <typename T> | |
869 struct rv_ref_impl { | |
870 typedef BOOST_RV_REF(T) type; | |
871 }; | |
872 | |
873 template <typename T> | |
874 struct rv_ref : | |
875 boost::detail::if_true< | |
876 boost::is_class<T>::value | |
877 >::BOOST_NESTED_TEMPLATE then < | |
878 boost::unordered::detail::rv_ref_impl<T>, | |
879 please_ignore_this_overload | |
880 >::type | |
881 {}; | |
882 | |
883 # define BOOST_UNORDERED_RV_REF(T) \ | |
884 typename boost::unordered::detail::rv_ref<T>::type | |
885 #endif | |
886 }}} | |
887 | |
888 #endif |