📄 hash_table_impl.hpp
字号:
} else { // The deleted node is at the end of the group, so the // first node in the group is pointing to it. // Find that to change its pointer. link_ptr it = n->group_prev_; while(prev_in_group(it) != *pos) { it = prev_in_group(it); } prev_in_group(it) = n->group_prev_; } *pos = next; --size_; } size_type unlink_group(link_ptr* pos) { size_type count = group_count(*pos); size_ -= count; *pos = next_group(*pos); return count; }#else void unlink_node(iterator_base n) { link_ptr* pos = get_for_erase(n); *pos = (*pos)->next_; --size_; } size_type unlink_group(link_ptr* pos) { *pos = (*pos)->next_; --size_; return 1; }#endif void unlink_nodes(iterator_base n) { link_ptr* it = get_for_erase(n); split_group(*it); unordered_detail::reset(*it); size_ -= node_count(n.node_); } void unlink_nodes(iterator_base begin, iterator_base end) { BOOST_ASSERT(begin.bucket_ == end.bucket_); size_ -= node_count(begin.node_, end.node_); link_ptr* it = get_for_erase(begin); split_group(*it, end.node_); *it = end.node_; } void unlink_nodes(bucket_ptr base, iterator_base end) { BOOST_ASSERT(base == end.bucket_); split_group(end.node_); link_ptr ptr(base->next_); base->next_ = end.node_; size_ -= node_count(ptr, end.node_); }#if BOOST_UNORDERED_EQUIVALENT_KEYS // Break a ciruclar list into two, with split as the beginning // of the second group (if split is at the beginning then don't // split). static inline link_ptr split_group(link_ptr split) { // If split is at the beginning of the group then there's // nothing to split. if(prev_in_group(split)->next_ != split) return unordered_detail::null_ptr<link_ptr>(); // Find the start of the group. link_ptr start = split; do { start = prev_in_group(start); } while(prev_in_group(start)->next_ == start); link_ptr last = prev_in_group(start); prev_in_group(start) = prev_in_group(split); prev_in_group(split) = last; return start; } static inline void split_group(link_ptr split1, link_ptr split2) { link_ptr begin1 = split_group(split1); link_ptr begin2 = split_group(split2); if(BOOST_UNORDERED_BORLAND_BOOL(begin1) && split1 == begin2) { link_ptr end1 = prev_in_group(begin1); prev_in_group(begin1) = prev_in_group(begin2); prev_in_group(begin2) = end1; } }#else static inline void split_group(link_ptr) { } static inline void split_group(link_ptr, link_ptr) { }#endif // copy_group // // Basic exception safety. // If it throws, it only copies some of the nodes in the group.#if BOOST_UNORDERED_EQUIVALENT_KEYS void copy_group(link_ptr it, bucket_ptr dst) { node_constructor a(allocators_); link_ptr end = next_group(it); a.construct(get_value(it)); // throws link_ptr n = link_node_in_bucket(a, dst); for(it = it->next_; it != end; it = it->next_) { a.construct(get_value(it)); // throws link_node(a, n); } }#else void copy_group(link_ptr it, bucket_ptr dst) { node_constructor a(allocators_); a.construct(get_value(it)); // throws link_node_in_bucket(a, dst); }#endif // Delete Node // // Remove a node, or a range of nodes, from a bucket, and destroy // them. // // no throw void delete_to_bucket_end(link_ptr begin) { while(begin) { link_ptr node = begin; begin = begin->next_; allocators_.destroy(node); } } void delete_nodes(link_ptr begin, link_ptr end) { while(begin != end) { link_ptr node = begin; begin = begin->next_; allocators_.destroy(node); } }#if BOOST_UNORDERED_EQUIVALENT_KEYS void delete_group(link_ptr first_node) { delete_nodes(first_node, prev_in_group(first_node)->next_); }#else void delete_group(link_ptr node) { allocators_.destroy(node); }#endif // Clear // // Remove all the nodes. // // no throw void clear_bucket(bucket_ptr b) { link_ptr first_node = b->next_; unordered_detail::reset(b->next_); delete_to_bucket_end(first_node); } void clear() { bucket_ptr begin = cached_begin_bucket_; bucket_ptr end = buckets_end(); size_ = 0; cached_begin_bucket_ = end; while(begin != end) { clear_bucket(begin); ++begin; } } // Erase // // no throw iterator_base erase(iterator_base r) { BOOST_ASSERT(r != end()); iterator_base next = r; next.increment(); unlink_node(r); allocators_.destroy(r.node_); // r has been invalidated but its bucket is still valid recompute_begin_bucket(r.bucket_, next.bucket_); return next; } iterator_base erase_range(iterator_base r1, iterator_base r2) { if(r1 != r2) { BOOST_ASSERT(r1 != end()); if (r1.bucket_ == r2.bucket_) { unlink_nodes(r1, r2); delete_nodes(r1.node_, r2.node_); // No need to call recompute_begin_bucket because // the nodes are only deleted from one bucket, which // still contains r2 after the erase. BOOST_ASSERT(!r1.bucket_->empty()); } else { BOOST_ASSERT(r1.bucket_ < r2.bucket_); unlink_nodes(r1); delete_to_bucket_end(r1.node_); bucket_ptr i = r1.bucket_; for(++i; i != r2.bucket_; ++i) { size_ -= node_count(i->next_); clear_bucket(i); } if(r2 != end()) { link_ptr first = r2.bucket_->next_; unlink_nodes(r2.bucket_, r2); delete_nodes(first, r2.node_); } // r1 has been invalidated but its bucket is still // valid. recompute_begin_bucket(r1.bucket_, r2.bucket_); } } return r2; } // recompute_begin_bucket // // After an erase cached_begin_bucket_ might be left pointing to // an empty bucket, so this is called to update it // // no throw void recompute_begin_bucket(bucket_ptr b) { BOOST_ASSERT(!(b < cached_begin_bucket_)); if(b == cached_begin_bucket_) { if (size_ != 0) { while (cached_begin_bucket_->empty()) ++cached_begin_bucket_; } else { cached_begin_bucket_ = buckets_end(); } } } // This is called when a range has been erased // // no throw void recompute_begin_bucket(bucket_ptr b1, bucket_ptr b2) { BOOST_ASSERT(!(b1 < cached_begin_bucket_) && !(b2 < b1)); BOOST_ASSERT(b2 == buckets_end() || !b2->empty()); if(b1 == cached_begin_bucket_ && b1->empty()) cached_begin_bucket_ = b2; } size_type erase_group(link_ptr* it, bucket_ptr bucket) { link_ptr pos = *it; size_type count = unlink_group(it); delete_group(pos); this->recompute_begin_bucket(bucket); return count; } };#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG) template <> class BOOST_UNORDERED_TABLE_DATA<int> { public: typedef int size_type; typedef int iterator_base; };#endif // // Hash Table // template <typename ValueType, typename KeyType, typename Hash, typename Pred, typename Alloc> class BOOST_UNORDERED_TABLE { typedef BOOST_UNORDERED_TABLE_DATA<Alloc> data; typedef BOOST_DEDUCED_TYPENAME data::node_constructor node_constructor; typedef BOOST_DEDUCED_TYPENAME data::bucket_ptr bucket_ptr; typedef BOOST_DEDUCED_TYPENAME data::link_ptr link_ptr; public: typedef BOOST_DEDUCED_TYPENAME data::value_allocator value_allocator; typedef BOOST_DEDUCED_TYPENAME data::node_allocator node_allocator; // Type definitions typedef KeyType key_type; typedef Hash hasher; typedef Pred key_equal; typedef ValueType value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; // iterators typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base; private: typedef boost::unordered_detail::buffered_functions<Hash, Pred> function_store; typedef BOOST_DEDUCED_TYPENAME function_store::functions functions; typedef BOOST_DEDUCED_TYPENAME function_store::functions_ptr functions_ptr; function_store functions_; float mlf_; size_type max_load_; public: data data_; // Constructors // // In the constructors, if anything throws an exception, // BOOST_UNORDERED_TABLE_DATA's destructor will clean up.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -