/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
bm_word_t* map = derived->reallocate(old_map, old_size_in_words, new_size_in_words); if (clear && (new_size_in_bits > old_size_in_bits)) { // If old_size_in_bits is not word-aligned, then the preceding // copy can include some trailing bits in the final copied word // that also need to be cleared. See clear_range_within_word.
bm_word_t mask = bit_mask(old_size_in_bits) - 1;
map[raw_to_words_align_down(old_size_in_bits)] &= mask; // Clear the remaining full words.
clear_range_of_words(map, old_size_in_words, new_size_in_words);
}
void BitMap::set_range_within_word(idx_t beg, idx_t end) { // With a valid range (beg <= end), this test ensures that end != 0, as // required by inverted_bit_mask_for_range. Also avoids an unnecessary write. if (beg != end) {
bm_word_t mask = inverted_bit_mask_for_range(beg, end);
*word_addr(beg) |= ~mask;
}
}
void BitMap::clear_range_within_word(idx_t beg, idx_t end) { // With a valid range (beg <= end), this test ensures that end != 0, as // required by inverted_bit_mask_for_range. Also avoids an unnecessary write. if (beg != end) {
bm_word_t mask = inverted_bit_mask_for_range(beg, end);
*word_addr(beg) &= mask;
}
}
void BitMap::par_put_range_within_word(idx_t beg, idx_t end, bool value) {
assert(value == 0 || value == 1, "0 for clear, 1 for set"); // With a valid range (beg <= end), this test ensures that end != 0, as // required by inverted_bit_mask_for_range. Also avoids an unnecessary write. if (beg != end) { volatile bm_word_t* pw = word_addr(beg);
bm_word_t w = Atomic::load(pw);
bm_word_t mr = inverted_bit_mask_for_range(beg, end);
bm_word_t nw = value ? (w | ~mr) : (w & mr); while (true) {
bm_word_t res = Atomic::cmpxchg(pw, w, nw); if (res == w) break;
w = res;
nw = value ? (w | ~mr) : (w & mr);
}
}
}
if (beg_full_word < end_full_word) { // The range includes at least one full word.
set_range_within_word(beg, bit_index(beg_full_word));
set_range_of_words(beg_full_word, end_full_word);
set_range_within_word(bit_index(end_full_word), end);
} else { // The range spans at most 2 partial words.
idx_t boundary = MIN2(bit_index(beg_full_word), end);
set_range_within_word(beg, boundary);
set_range_within_word(boundary, end);
}
}
if (beg_full_word < end_full_word) { // The range includes at least one full word.
clear_range_within_word(beg, bit_index(beg_full_word));
clear_range_of_words(beg_full_word, end_full_word);
clear_range_within_word(bit_index(end_full_word), end);
} else { // The range spans at most 2 partial words.
idx_t boundary = MIN2(bit_index(beg_full_word), end);
clear_range_within_word(beg, boundary);
clear_range_within_word(boundary, end);
}
}
bool BitMap::is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word) { // There is little point to call large version on small ranges. // Need to check carefully, keeping potential idx_t over/underflow in mind, // because beg_full_word > end_full_word can occur when beg and end are in // the same word. // The threshold should be at least one word.
STATIC_ASSERT(small_range_words >= 1); return beg_full_word + small_range_words >= end_full_word;
}
if (is_small_range_of_words(beg_full_word, end_full_word)) {
set_range(beg, end); return;
}
// The range includes at least one full word.
set_range_within_word(beg, bit_index(beg_full_word));
set_large_range_of_words(beg_full_word, end_full_word);
set_range_within_word(bit_index(end_full_word), end);
}
if (is_small_range_of_words(beg_full_word, end_full_word)) {
clear_range(beg, end); return;
}
// The range includes at least one full word.
clear_range_within_word(beg, bit_index(beg_full_word));
clear_large_range_of_words(beg_full_word, end_full_word);
clear_range_within_word(bit_index(end_full_word), end);
}
// Return true to indicate that this thread changed // the bit, false to indicate that someone else did. // In either case, the requested bit is in the // requested state some time during the period that // this thread is executing this call. More importantly, // if no other thread is executing an action to // change the requested bit to a state other than // the one that this thread is trying to set it to, // then the bit is in the expected state // at exit from this method. However, rather than // make such a strong assertion here, based on // assuming such constrained use (which though true // today, could change in the future to service some // funky parallel algorithm), we encourage callers // to do such verification, as and when appropriate. bool BitMap::par_at_put(idx_t bit, bool value) { return value ? par_set_bit(bit) : par_clear_bit(bit);
}
if (beg_full_word < end_full_word) { // The range includes at least one full word.
par_put_range_within_word(beg, bit_index(beg_full_word), value); if (value) {
set_range_of_words(beg_full_word, end_full_word);
} else {
clear_range_of_words(beg_full_word, end_full_word);
}
par_put_range_within_word(bit_index(end_full_word), end, value);
} else { // The range spans at most 2 partial words.
idx_t boundary = MIN2(bit_index(beg_full_word), end);
par_put_range_within_word(beg, boundary, value);
par_put_range_within_word(boundary, end, value);
}
if (is_small_range_of_words(beg_full_word, end_full_word)) {
par_at_put_range(beg, end, value); return;
}
// The range includes at least one full word.
par_put_range_within_word(beg, bit_index(beg_full_word), value); if (value) {
set_large_range_of_words(beg_full_word, end_full_word);
} else {
clear_large_range_of_words(beg_full_word, end_full_word);
}
par_put_range_within_word(bit_index(end_full_word), end, value);
}
// Get the low tail_bits of value, which is the last partial word of a map. inline bm_word_t tail_of_map(bm_word_t value, idx_t tail_bits) { return value & tail_mask(tail_bits);
}
// Compute the new last word of a map with a non-aligned length. // new_value has the new trailing bits of the map in the low tail_bits. // old_value is the last word of the map, including bits beyond the end. // Returns old_value with the low tail_bits replaced by the corresponding // bits in new_value. inline bm_word_t merge_tail_of_map(bm_word_t new_value,
bm_word_t old_value,
idx_t tail_bits) {
bm_word_t mask = tail_mask(tail_bits); return (new_value & mask) | (old_value & ~mask);
}
bool BitMap::contains(const BitMap& other) const {
assert(size() == other.size(), "must have same size"); const bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map();
idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { // false if other bitmap has bits set which are clear in this bitmap. if ((~dest_map[index] & other_map[index]) != 0) returnfalse;
}
idx_t rest = bit_in_word(size()); // true unless there is a partial-word tail in which the other // bitmap has bits set which are clear in this bitmap. return (rest == 0) || tail_of_map(~dest_map[limit] & other_map[limit], rest) == 0;
}
bool BitMap::intersects(const BitMap& other) const {
assert(size() == other.size(), "must have same size"); const bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map();
idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { if ((dest_map[index] & other_map[index]) != 0) returntrue;
}
idx_t rest = bit_in_word(size()); // false unless there is a partial-word tail with non-empty intersection. return (rest > 0) && tail_of_map(dest_map[limit] & other_map[limit], rest) != 0;
}
if (beg_full_word < end_full_word) { // The range includes at least one full word.
sum += count_one_bits_within_word(beg, bit_index(beg_full_word));
sum += count_one_bits_in_range_of_words(beg_full_word, end_full_word);
sum += count_one_bits_within_word(bit_index(end_full_word), end);
} else { // The range spans at most 2 partial words.
idx_t boundary = MIN2(bit_index(beg_full_word), end);
sum += count_one_bits_within_word(beg, boundary);
sum += count_one_bits_within_word(boundary, end);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.