add all_set() function on bitfield and automatically call inc_refcount_all or dec_refcount_all if all bits are set in a bitfield

This commit is contained in:
Arvid Norberg 2012-05-02 18:55:58 +00:00
parent ada35c021a
commit 10b64a7761
3 changed files with 34 additions and 2 deletions

View File

@ -81,6 +81,28 @@ namespace libtorrent
m_bytes[index / 8] &= ~(0x80 >> (index & 7));
}
// returns true if all bits in the bitfield are set
bool all_set() const
{
const int num_words = m_size / 32;
const int num_bytes = m_size / 8;
boost::uint32_t* bits = (boost::uint32_t*)m_bytes;
for (int i = 0; i < num_words; ++i)
{
if (bits[i] != 0xffffffff) return false;
}
for (int i = num_words * 4; i < num_bytes; ++i)
{
if (m_bytes[i] != 0xff) return false;
}
int rest = m_size - num_bytes * 8;
boost::uint8_t mask = 0xff << (8-rest);
if (rest > 0 && (m_bytes[num_bytes] & mask) != mask)
return false;
return true;
}
void set_bit(int index)
{
TORRENT_ASSERT(index >= 0);

View File

@ -539,7 +539,10 @@ namespace libtorrent
{
if (has_picker())
{
m_picker->inc_refcount(bits);
if (bits.all_set())
m_picker->inc_refcount_all();
else
m_picker->inc_refcount(bits);
}
#ifdef TORRENT_DEBUG
else
@ -567,7 +570,10 @@ namespace libtorrent
{
if (has_picker())
{
m_picker->dec_refcount(bits);
if (bits.all_set())
m_picker->dec_refcount_all();
else
m_picker->dec_refcount(bits);
}
#ifdef TORRENT_DEBUG
else

View File

@ -1797,6 +1797,7 @@ int test_main()
test1.set_bit(1);
test1.set_bit(9);
TEST_CHECK(test1.count() == 3);
TEST_CHECK(test1.all_set() == false);
test1.clear_bit(2);
TEST_CHECK(test1.count() == 2);
int distance = std::distance(test1.begin(), test1.end());
@ -1818,6 +1819,9 @@ int test_main()
test1.set_bit(1);
test1.resize(1);
TEST_CHECK(test1.count() == 1);
test1.resize(100, true);
TEST_CHECK(test1.all_set() == true);
return 0;
}