From bf6bb54c315ba6cc7a8e40769d11802745bc1676 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 8 Jun 2006 00:21:08 +0000 Subject: [PATCH] copy BitArray by reference --- panda/src/putil/bitArray.I | 17 +++++++++++++++++ panda/src/putil/bitArray.cxx | 31 ++++++++++++++++++++++++------- panda/src/putil/bitArray.h | 4 +++- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/panda/src/putil/bitArray.I b/panda/src/putil/bitArray.I index de63efcb6f..d6f8e334cd 100755 --- a/panda/src/putil/bitArray.I +++ b/panda/src/putil/bitArray.I @@ -518,3 +518,20 @@ operator >> (int shift) const { result >>= shift; return result; } + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::copy_on_write +// Access: Private +// Description: Called internally just before writing to the _array +// member, this makes a new copy of _array if it appears +// to be shared with any other objects--thus achieving +// copy-on-write. +//////////////////////////////////////////////////////////////////// +INLINE void BitArray:: +copy_on_write() { + if (_array.get_ref_count() > 1) { + PTA(MaskType) new_array; + new_array.v() = _array.v(); + _array = new_array; + } +} diff --git a/panda/src/putil/bitArray.cxx b/panda/src/putil/bitArray.cxx index ce61bc2e1a..0e2253669c 100755 --- a/panda/src/putil/bitArray.cxx +++ b/panda/src/putil/bitArray.cxx @@ -35,7 +35,7 @@ is_zero() const { } // Start from the high end, since that's more likely to be nonzero. - Array::const_reverse_iterator ai; + Array::reverse_iterator ai; for (ai = _array.rbegin(); ai != _array.rend(); ++ai) { if ((*ai) != 0) { return false; @@ -157,6 +157,7 @@ clear_range(int low_bit, int size) { void BitArray:: invert_in_place() { _highest_bits = !_highest_bits; + copy_on_write(); Array::iterator ai; for (ai = _array.begin(); ai != _array.end(); ++ai) { (*ai) = ~(*ai); @@ -328,6 +329,8 @@ void BitArray:: operator &= (const BitArray &other) { size_t num_common_words = min(_array.size(), other._array.size()); + copy_on_write(); + // Consider the words that are on top of either array. if (other._array.size() < _array.size() && !other._highest_bits) { // The other array has fewer actual words, and the top n words of @@ -365,6 +368,8 @@ void BitArray:: operator |= (const BitArray &other) { size_t num_common_words = min(_array.size(), other._array.size()); + copy_on_write(); + // Consider the words that are on top of either array. if (other._array.size() < _array.size() && other._highest_bits) { // The other array has fewer actual words, and the top n words of @@ -402,6 +407,8 @@ void BitArray:: operator ^= (const BitArray &other) { size_t num_common_words = min(_array.size(), other._array.size()); + copy_on_write(); + // Consider the words that are on top of either array. if (other._array.size() < _array.size() && other._highest_bits) { // The other array has fewer actual words, and the top n words of @@ -478,7 +485,7 @@ operator <<= (int shift) { for (ai = _array.begin(); ai != _array.end(); ++ai) { new_array.push_back(*ai); } - _array.swap(new_array); + _array = new_array; } else { // Harder case--we have to shuffle bits between words. @@ -508,7 +515,7 @@ operator <<= (int shift) { next_bits |= ~MaskType::lower_on(b); } new_array.push_back(next_bits); - _array.swap(new_array); + _array = new_array; } normalize(); @@ -549,7 +556,7 @@ operator >>= (int shift) { for (ai = _array.begin() + w; ai != _array.end(); ++ai) { new_array.push_back(*ai); } - _array.swap(new_array); + _array = new_array; } else { // Harder case--we have to shuffle bits between words. @@ -576,7 +583,7 @@ operator >>= (int shift) { next_bits |= ~MaskType::lower_on(upshift_count); } new_array.push_back(next_bits); - _array.swap(new_array); + _array = new_array; } normalize(); @@ -604,6 +611,8 @@ generate_hash(ChecksumHashGenerator &hashgen) const { //////////////////////////////////////////////////////////////////// void BitArray:: ensure_has_word(int n) { + copy_on_write(); + if (_highest_bits) { while (n >= (int)_array.size()) { _array.push_back(MaskType::all_on()); @@ -625,12 +634,20 @@ ensure_has_word(int n) { void BitArray:: normalize() { if (_highest_bits) { - while (!_array.empty() && _array.back() == MaskType::all_on()) { + if (!_array.empty() && _array.back() == MaskType::all_on()) { + copy_on_write(); _array.pop_back(); + while (!_array.empty() && _array.back() == MaskType::all_on()) { + _array.pop_back(); + } } } else { - while (!_array.empty() && _array.back().is_zero()) { + if (!_array.empty() && _array.back().is_zero()) { + copy_on_write(); _array.pop_back(); + while (!_array.empty() && _array.back().is_zero()) { + _array.pop_back(); + } } } } diff --git a/panda/src/putil/bitArray.h b/panda/src/putil/bitArray.h index 0e11afc1b3..0b689c8c50 100755 --- a/panda/src/putil/bitArray.h +++ b/panda/src/putil/bitArray.h @@ -25,6 +25,7 @@ #include "numeric_types.h" #include "typedObject.h" #include "indent.h" +#include "pointerToArray.h" #include "checksumHashGenerator.h" @@ -121,11 +122,12 @@ public: void generate_hash(ChecksumHashGenerator &hashgen) const; private: + INLINE void copy_on_write(); void ensure_has_word(int n); void normalize(); private: - typedef pvector Array; + typedef PTA(MaskType) Array; Array _array; int _highest_bits; // Either 0 or 1.