BitfieldMan: Rewrite getCompletedLength and countMissingBlockNow

Rewritten so that no memory allocation is required for these
functions.
pull/103/head
Tatsuhiro Tsujikawa 2013-07-03 22:40:28 +09:00
parent 0d85fb0df3
commit 211f685add
2 changed files with 70 additions and 50 deletions

View File

@ -516,13 +516,9 @@ size_t BitfieldMan::countMissingBlock() const {
size_t BitfieldMan::countMissingBlockNow() const {
if(filterEnabled_) {
array_ptr<unsigned char> temp(new unsigned char[bitfieldLength_]);
for(size_t i = 0; i < bitfieldLength_; ++i) {
temp[i] = bitfield_[i]&filterBitfield_[i];
}
size_t count = bitfield::countSetBit(filterBitfield_, blocks_)-
bitfield::countSetBit(temp, blocks_);
return count;
return bitfield::countSetBit(filterBitfield_, blocks_) -
bitfield::countSetBitSlow(array(bitfield_)&array(filterBitfield_),
blocks_);
} else {
return blocks_-bitfield::countSetBit(bitfield_, blocks_);
}
@ -749,36 +745,39 @@ int64_t BitfieldMan::getFilteredTotalLengthNow() const {
}
}
int64_t BitfieldMan::getCompletedLength(bool useFilter) const {
unsigned char* temp;
if(useFilter) {
temp = new unsigned char[bitfieldLength_];
for(size_t i = 0; i < bitfieldLength_; ++i) {
temp[i] = bitfield_[i];
if(filterEnabled_) {
temp[i] &= filterBitfield_[i];
}
}
} else {
temp = bitfield_;
}
size_t completedBlocks = bitfield::countSetBit(temp, blocks_);
namespace {
template<typename Array, typename CountFun>
int64_t computeCompletedLength(const Array& bitfield,
const BitfieldMan* btman,
CountFun cntfun)
{
size_t nbits = btman->countBlock();
size_t completedBlocks = cntfun(bitfield, nbits);
int64_t completedLength = 0;
if(completedBlocks == 0) {
completedLength = 0;
} else {
if(bitfield::test(temp, blocks_, blocks_-1)) {
completedLength =
((int64_t)completedBlocks-1)*blockLength_+getLastBlockLength();
if(bitfield::test(bitfield, nbits, nbits - 1)) {
completedLength = ((int64_t)completedBlocks-1)*btman->getBlockLength() +
btman->getLastBlockLength();
} else {
completedLength = ((int64_t)completedBlocks)*blockLength_;
completedLength = ((int64_t)completedBlocks)*btman->getBlockLength();
}
}
if(useFilter) {
delete [] temp;
}
return completedLength;
}
} // namespace
int64_t BitfieldMan::getCompletedLength(bool useFilter) const {
if(useFilter && filterEnabled_) {
auto arr = array(bitfield_)&array(filterBitfield_);
return computeCompletedLength(arr,
this,
&bitfield::countSetBitSlow<decltype(arr)>);
} else {
return computeCompletedLength(bitfield_, this, &bitfield::countSetBit);
}
}
int64_t BitfieldMan::getCompletedLengthNow() const {
return getCompletedLength(false);

View File

@ -72,9 +72,7 @@ inline bool test(const Array& bitfield, size_t nbits, size_t index)
return (bitfield[index/8]&mask) != 0;
}
inline size_t countBit32(uint32_t n)
{
static const int nbits[] = {
const int cntbits[] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
@ -91,12 +89,15 @@ inline size_t countBit32(uint32_t n)
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
};
};
inline size_t countBit32(uint32_t n)
{
return
nbits[n&0xffu]+
nbits[(n >> 8)&0xffu]+
nbits[(n >> 16)&0xffu]+
nbits[(n >> 24)&0xffu];
cntbits[n&0xffu]+
cntbits[(n >> 8)&0xffu]+
cntbits[(n >> 16)&0xffu]+
cntbits[(n >> 24)&0xffu];
}
// Counts set bit in bitfield.
@ -125,6 +126,26 @@ inline size_t countSetBit(const unsigned char* bitfield, size_t nbits)
return count;
}
// Counts set bit in bitfield. This is a bit slower than countSetBit
// but can accept array template expression as bitfield.
template<typename Array>
size_t countSetBitSlow(const Array& bitfield, size_t nbits)
{
if(nbits == 0) {
return 0;
}
size_t count = 0;
size_t to = (nbits+7)/8;
if(to > 1) {
for(size_t i = 0; i < to - 1; ++i) {
count += cntbits[static_cast<unsigned char>(bitfield[i])];
}
}
count +=
cntbits[static_cast<unsigned char>(bitfield[to - 1])&lastByteMask(nbits)];
return count;
}
void flipBit(unsigned char* data, size_t length, size_t bitIndex);
// Stores first set bit index of bitfield to index. bitfield contains