Esempio n. 1
0
    void grouped_node_base<A>::unlink_nodes(bucket& b,
        node_ptr begin, node_ptr end)
    {
        node_ptr* pos = &next_group(begin);

        if(*pos != begin) {
            // The node is at the beginning of a group.

            // Find the previous node pointer:
            pos = &b.next_;
            while(*pos != begin) pos = &next_group(*pos);

            // Remove from group
            if(BOOST_UNORDERED_BORLAND_BOOL(end)) split_group(end);
        }
        else {
            node_ptr group1 = split_group(begin);
            if(BOOST_UNORDERED_BORLAND_BOOL(end)) {
                node_ptr group2 = split_group(end);

                if(begin == group2) {
                    node_ptr end1 = get(group1).group_prev_;
                    node_ptr end2 = get(group2).group_prev_;
                    get(group1).group_prev_ = end2;
                    get(group2).group_prev_ = end1;
                }
            }
        }
        *pos = end;
    }
    inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
        hash_unique_table<H, P, A, K>::emplace_impl(key_type const& k,
            Args&&... args)
    {
        // No side effects in this initial code
        std::size_t hash_value = this->hash_function()(k);
        bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
        node_ptr pos = this->find_iterator(bucket, k);

        if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
            // Found an existing key, return it (no throw).
            return emplace_return(iterator_base(bucket, pos), false);

        } else {
            // Doesn't already exist, add to bucket.
            // Side effects only in this block.

            // Create the node before rehashing in case it throws an
            // exception (need strong safety in such a case).
            node_constructor a(*this);
            a.construct(std::forward<Args>(args)...);

            // reserve has basic exception safety if the hash function
            // throws, strong otherwise.
            if(this->reserve_for_insert(this->size_ + 1))
                bucket = this->bucket_ptr_from_hash(hash_value);

            // Nothing after this point can throw.

            return emplace_return(
                iterator_base(bucket, add_node(a, bucket)),
                true);
        }
    }
    inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
    hash_unique_table<H, P, A, K>::emplace_impl_with_node(node_constructor& a)
    {
        // No side effects in this initial code
        key_type const& k = this->get_key(a.value());
        std::size_t hash_value = this->hash_function()(k);
        bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
        node_ptr pos = this->find_iterator(bucket, k);
        
        if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
            // Found an existing key, return it (no throw).
            return emplace_return(iterator_base(bucket, pos), false);
        } else {
            // reserve has basic exception safety if the hash function
            // throws, strong otherwise.
            if(this->reserve_for_insert(this->size_ + 1))
                bucket = this->bucket_ptr_from_hash(hash_value);

            // Nothing after this point can throw.

            return emplace_return(
                iterator_base(bucket, add_node(a, bucket)),
                true);
        }
    }
Esempio n. 4
0
     inline node_ptr add_node(
             node_constructor& a,
             std::size_t bucket_index,
             std::size_t hash,
             node_ptr pos)
     {
         node_ptr n = a.release();
         node::set_hash(n, hash);
 
         if(BOOST_UNORDERED_BORLAND_BOOL(pos)) {
             node::add_after_node(n, pos);
             if (n->next_) {
                 std::size_t next_bucket =
                     node::get_hash(n->next_) % this->bucket_count_;
                 if (next_bucket != bucket_index) {
                     this->buckets_[next_bucket].next_ = n;
                 }
             }
         }
         else {
             bucket_ptr b = this->get_bucket(bucket_index);
 
             if (!b->next_)
             {
                 bucket_ptr start_node =
                     this->get_bucket(this->bucket_count_);
                 
                 if (BOOST_UNORDERED_BORLAND_BOOL(start_node->next_)) {
                     this->buckets_[
                         node::get_hash(start_node->next_) %
                             this->bucket_count_].next_ = n;
                 }
 
                 b->next_ = start_node;
                 n->next_ = start_node->next_;
                 start_node->next_ = n;
             }
             else
             {
                 n->next_ = b->next_->next_;
                 b->next_->next_ = n;
             }
         }
         ++this->size_;
         return n;
     }
Esempio n. 5
0
    void grouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
    {
        node_ptr next = n->next_;
        node_ptr* pos = &next_group(n);

        if(*pos != n) {
            // The node is at the beginning of a group.

            // Find the previous node pointer:
            pos = &b.next_;
            while(*pos != n) pos = &next_group(*pos);

            // Remove from group
            if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
                get(next).group_prev_ == n)
            {
                get(next).group_prev_ = get(n).group_prev_;
            }
        }
        else if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
            get(next).group_prev_ == n)
        {
            // The deleted node is not at the end of the group, so
            // change the link from the next node.
            get(next).group_prev_ = get(n).group_prev_;
        }
        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.
            node_ptr x = get(n).group_prev_;
            while(get(x).group_prev_ != n) {
                x = get(x).group_prev_;
            }
            get(x).group_prev_ = get(n).group_prev_;
        }
        *pos = next;
    }
    bool hash_unique_table<H, P, A, K>
        ::equals(hash_unique_table<H, P, A, K> const& other) const
    {
        if(this->size_ != other.size_) return false;
        if(!this->size_) return true;

        bucket_ptr end = this->get_bucket(this->bucket_count_);
        for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
        {
            node_ptr it1 = i->next_;
            while(BOOST_UNORDERED_BORLAND_BOOL(it1))
            {
                node_ptr it2 = other.find_iterator(this->get_key_from_ptr(it1));
                if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
                if(!extractor::compare_mapped(
                    node::get_value(it1), node::get_value(it2)))
                    return false;
                it1 = it1->next_;
            }
        }

        return true;
    }
    inline void hash_unique_table<H, P, A, K>::insert_range_impl(
        key_type const&, InputIt i, InputIt j)
    {
        node_constructor a(*this);

        if(!this->size_) {
            a.construct(*i);
            this->emplace_empty_impl_with_node(a, 1);
            ++i;
            if(i == j) return;
        }

        do {
            // No side effects in this initial code
            // Note: can't use get_key as '*i' might not be value_type - it could
            // be a pair with first_types as key_type without const or a
            // different second_type.
            key_type const& k = extractor::extract(*i);
            std::size_t hash_value = this->hash_function()(k);
            bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
            node_ptr pos = this->find_iterator(bucket, k);

            if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) {
                // Doesn't already exist, add to bucket.
                // Side effects only in this block.

                // Create the node before rehashing in case it throws an
                // exception (need strong safety in such a case).
                a.construct(*i);

                // reserve has basic exception safety if the hash function
                // throws, strong otherwise.
                if(this->size_ + 1 >= this->max_load_) {
                    this->reserve_for_insert(this->size_ + insert_size(i, j));
                    bucket = this->bucket_ptr_from_hash(hash_value);
                }

                // Nothing after this point can throw.
                add_node(a, bucket);
            }
        } while(++i != j);
    }
    BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::value_type&
        hash_unique_table<H, P, A, K>::operator[](key_type const& k)
    {
        typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;

        std::size_t hash_value = this->hash_function()(k);
        bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
        
        if(!this->buckets_) {
            node_constructor a(*this);
            a.construct_pair(k, (mapped_type*) 0);
            return *this->emplace_empty_impl_with_node(a, 1);
        }

        node_ptr pos = this->find_iterator(bucket, k);

        if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
            return node::get_value(pos);
        }
        else {
            // Side effects only in this block.

            // Create the node before rehashing in case it throws an
            // exception (need strong safety in such a case).
            node_constructor a(*this);
            a.construct_pair(k, (mapped_type*) 0);

            // reserve has basic exception safety if the hash function
            // throws, strong otherwise.
            if(this->reserve_for_insert(this->size_ + 1))
                bucket = this->bucket_ptr_from_hash(hash_value);

            // Nothing after this point can throw.

            return node::get_value(add_node(a, bucket));
        }
    }