open-source-search-engine/Flags.cpp
mwells 87285ba3cd use gbmemcpy not memcpy so we can get profiler working again
since memcpy can't be interrupted and backtrace() called.
2015-01-13 12:25:42 -07:00

328 lines
10 KiB
C++

#include "Mem.h"
#include "Flags.h"
#include "Sanity.h"
#include "Timer.h"
const int32_t Flags::NoMin = 2147483647;
const int32_t Flags::NoMax = -1;
Flags::Flags() {
m_flags = NULL;
m_numFlags = 0;
m_numSet = 0;
m_highestSet = NoMax;
m_lowestSet = NoMin;
}
Flags::~Flags() {
if ( m_flags ) {
mfree( m_flags, m_numFlags*sizeof(char), "Flags" );
m_flags = NULL;
}
}
void Flags::reset() {
if ( m_flags ) memset( m_flags, 0, m_numFlags*sizeof(char) );
m_numSet = 0;
m_highestSet = NoMax;
m_lowestSet = NoMin;
}
bool Flags::resize( int32_t size ) {
if ( size < 0 ) return false;
if ( size == m_numFlags ) return true;
char *newFlags = (char *)mcalloc( size*sizeof(char), "Flags" );
if ( ! newFlags ) return false;
m_numSet = 0;
m_highestSet = NoMax;
m_lowestSet = NoMin;
if ( m_flags ) {
// copy as many of old flags over as possible
int32_t min = m_numFlags;
if ( min > size ) min = size;
gbmemcpy( newFlags, m_flags, min*sizeof(char) );
mfree( m_flags, m_numFlags*sizeof(char), "Flags" );
m_flags = NULL;
// find new values for member variables
for ( int32_t i = 0; i < min; i++ ) {
if ( newFlags[i] ) {
m_numSet++;
if ( i > m_highestSet ) m_highestSet = i;
if ( i < m_lowestSet ) m_lowestSet = i;
}
}
}
m_flags = newFlags;
m_numFlags = size;
return (m_flags != NULL);
}
void Flags::setFlag( int32_t n, char set ) {
if ( m_flags[n] == set ) return;
// set the value of flag[n]
char prevSet = m_flags[n];
m_flags[n] = set;
// if just changing the value, we can stop right here
if ( prevSet && set ) return;
if ( set ) {
m_numSet++;
//GBASSERT( m_numSet <= m_numFlags );
if ( n < m_lowestSet ) m_lowestSet = n;
if ( n > m_highestSet ) m_highestSet = n;
//GBASSERT( m_highestSet >= m_lowestSet );
}
else {
m_numSet--;
// recalc m_lowestSet and m_highestSet
//GBASSERT( m_numSet >= 0);
if ( m_numSet == 0 ) {
m_lowestSet = NoMin;
m_highestSet = NoMax;
return;
}
if ( n == m_lowestSet ) {
for ( ; n <= m_highestSet ; n++ )
if ( m_flags[n] ) break;
if ( n < m_numFlags ) m_lowestSet = n;
else m_lowestSet = NoMin;
}
//GBASSERT( (m_numSet > 0) ? m_lowestSet != NoMin : true );
//GBASSERT( m_flags[m_lowestSet] );
if ( n == m_highestSet ) {
for ( ; n >= m_lowestSet ; n-- )
if ( m_flags[n] ) break;
if ( n >= 0 ) m_highestSet = n;
else m_highestSet = NoMax;
}
//GBASSERT( (m_numSet > 0) ? m_highestSet != NoMax : true );
//GBASSERT( m_flags[m_highestSet] );
//GBASSERT( m_highestSet >= m_lowestSet );
}
}
void Flags::dumpFlags() {
for ( int32_t i = 0; i < m_numFlags; i++ ) {
log(LOG_DEBUG, "AWL: Flag %"INT32":%d", i, (int)m_flags[i]);
}
}
void testFlags() {
log(LOG_DEBUG, "AWL: testing Flags...");
Flags flags;
log(LOG_DEBUG, "AWL: testing Flags 0...");
flags.resize( 0 );
GBASSERT( flags.getNumFlags() == 0 );
GBASSERT( flags.getNumSet() == 0 );
GBASSERT( flags.getLowestSet() == flags.NoMin );
GBASSERT( flags.getHighestSet() == flags.NoMax );
log(LOG_DEBUG, "AWL: testing Flags 1...");
flags.resize( 1 );
GBASSERT( flags.getNumFlags() == 1 );
GBASSERT( ! flags.getFlag( 0 ) );
GBASSERT( flags.getNumSet() == 0 );
GBASSERT( flags.getLowestSet() == flags.NoMin );
GBASSERT( flags.getHighestSet() == flags.NoMax );
log(LOG_DEBUG, "AWL: testing Flags 2...");
flags.setFlag( 0, true );
GBASSERT( flags.getFlag( 0 ) );
GBASSERT( flags.getLowestSet() == flags.getHighestSet() );
GBASSERT( flags.getLowestSet() == 0 );
GBASSERT( flags.getNumSet() == 1 );
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
log(LOG_DEBUG, "AWL: testing Flags 3...");
flags.setFlag( 0, false );
GBASSERT( ! flags.getFlag( 0 ) );
GBASSERT( flags.getLowestSet() == flags.NoMin );
GBASSERT( flags.getHighestSet() == flags.NoMax );
GBASSERT( flags.getNumSet() == 0 );
log(LOG_DEBUG, "AWL: testing Flags 4...");
flags.setFlag( 0, true );
flags.resize( 5 );
flags.setFlag( 1, true );
GBASSERT( flags.getNumFlags() == 5 );
GBASSERT( flags.getFlag(0) );
GBASSERT( flags.getFlag(1) );
GBASSERT( flags.getLowestSet() == 0 );
GBASSERT( flags.getHighestSet() == 1 );
GBASSERT( flags.getNumSet() == 2 );
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
log(LOG_DEBUG, "AWL: testing Flags 5...");
flags.setFlag( 3, true );
GBASSERT( flags.getFlag( 3 ) );
GBASSERT( flags.getLowestSet() == 0 );
GBASSERT( flags.getHighestSet() == 3 );
GBASSERT( flags.getNumSet() == 3 );
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
log(LOG_DEBUG, "AWL: testing Flags 6...");
flags.setFlag( 0, false );
GBASSERT( ! flags.getFlag( 0 ) );
GBASSERT( flags.getLowestSet() == 1 );
GBASSERT( flags.getHighestSet() == 3 );
GBASSERT( flags.getNumSet() == 2 );
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
log(LOG_DEBUG, "AWL: testing Flags 7...");
flags.setFlag( 0, true );
flags.setFlag( 2, true );
GBASSERT( flags.getFlag( 0 ) );
GBASSERT( flags.getFlag( 2 ) );
GBASSERT( flags.getLowestSet() == 0 );
GBASSERT( flags.getHighestSet() == 3 );
GBASSERT( flags.getNumSet() == 4 );
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
log(LOG_DEBUG, "AWL: testing Flags 8...");
flags.setFlag( 2, false );
GBASSERT( ! flags.getFlag( 2 ) );
GBASSERT( flags.getFlag( 0 ) );
GBASSERT( flags.getLowestSet() == 0 );
GBASSERT( flags.getHighestSet() == 3 );
GBASSERT( flags.getNumSet() == 3 );
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
log(LOG_DEBUG, "AWL: testing Flags 9...");
flags.setFlag( 2, 5 );
flags.setFlag( 3, false );
GBASSERT( flags.getFlag( 0 ) );
GBASSERT( 5 == flags.getFlag( 2 ) );
GBASSERT( ! flags.getFlag( 3 ) );
GBASSERT( flags.getLowestSet() == 0 );
GBASSERT( flags.getHighestSet() == 2 );
GBASSERT( flags.getNumSet() == 3 );
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
log(LOG_DEBUG, "AWL: testing Flags 10...");
flags.reset();
GBASSERT( flags.getNumFlags() == 5 );
for ( int32_t i = 0; i < flags.getNumFlags(); i++ ) {
GBASSERT( ! flags.getFlag( i ) );
}
GBASSERT( flags.getLowestSet() == flags.NoMin );
GBASSERT( flags.getHighestSet() == flags.NoMax );
GBASSERT( flags.getNumSet() == 0 );
log(LOG_DEBUG, "AWL: Testing Flags 11...");
flags.setFlag( 0, true );
flags.setFlag( 2, 0x33 );
flags.setFlag( 4, true );
GBASSERT( flags.getFlag( 0 ) );
GBASSERT( ! flags.getFlag( 1 ) );
GBASSERT( 0x33 == flags.getFlag( 2 ) );
GBASSERT( ! flags.getFlag( 3 ) );
GBASSERT( flags.getFlag( 4 ) );
GBASSERT( flags.getLowestSet() == 0 );
GBASSERT( flags.getHighestSet() == 4 );
GBASSERT( flags.getNumSet() == 3 );
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
log(LOG_DEBUG, "AWL: Testing Flags 12...");
flags.resize( 3 );
GBASSERT( flags.getNumFlags() == 3 );
GBASSERT( flags.getHighestSet() == 2 );
GBASSERT( flags.getLowestSet() == 0 );
GBASSERT( flags.getNumSet() == 2 );
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
log(LOG_DEBUG, "AWL: Testing Flags 13...");
flags.resize( 1 );
GBASSERT( flags.getNumFlags() == 1 );
GBASSERT( flags.getHighestSet() == 0 );
GBASSERT( flags.getLowestSet() == 0 );
GBASSERT( flags.getNumSet() == 1 );
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
log(LOG_DEBUG, "AWL: Testing Flags 14...");
flags.reset();
GBASSERT( flags.getNumSet() == 0 );
GBASSERT( flags.getNumFlags() == 1 );
GBASSERT( flags.getLowestSet() == flags.NoMin );
GBASSERT( flags.getHighestSet() == flags.NoMax );
for ( int32_t i = 0; i < flags.getNumFlags(); i++ ) {
GBASSERT( ! flags.getFlag( i ) );
}
const int32_t TESTCASESIZE = 100000;
if ( ! flags.resize( TESTCASESIZE ) ) {
log(LOG_DEBUG, "AWL: Cannot allocate memory to test Flags!");
return;
}
GBASSERT( flags.getNumSet() == 0 );
GBASSERT( flags.getNumFlags() == TESTCASESIZE );
GBASSERT( flags.getLowestSet() == flags.NoMin );
GBASSERT( flags.getHighestSet() == flags.NoMax );
//flags.dumpFlags();
for ( int32_t i = 0; i < flags.getNumFlags(); i++ ) {
GBASSERT( ! flags.getFlag( i ) );
}
log(LOG_DEBUG, "AWL: Testing Flags 15 (test case size:%"INT32")...",
TESTCASESIZE);
Timer timer;
timer.start();
int32_t cnt = 0;
int32_t ls = flags.NoMin;
int32_t hs = flags.NoMax;
for ( int32_t i = 0; i < TESTCASESIZE; i++ ) {
int32_t j = random() % TESTCASESIZE;
char r = random() % 2;
if ( 0 == r ) {
r = random() % 256;
if (r == 0) r = -1;
char wasSet = flags.getFlag( j );
if ( ! wasSet ) cnt++;
flags.setFlag( j, r );
GBASSERT( flags.getFlag( j ) == r );
//log(LOG_DEBUG, "AWL: set j:%"INT32" wasSet:%d set:%"INT32", cnt:%"INT32"",
// j, wasSet, flags.getNumSet(), cnt);
GBASSERT( flags.getNumSet() == cnt );
GBASSERT( flags.getNumFlags() == TESTCASESIZE );
if ( hs < j ) {
GBASSERT( flags.getHighestSet() == j );
hs = j;
}
if ( ls > j ) {
GBASSERT( flags.getLowestSet() == j );
ls = j;
}
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
}
else {
char wasSet = flags.getFlag( j );
if ( wasSet ) cnt--;
flags.setFlag( j, false );
if ( ls == j ) {
GBASSERT( flags.getLowestSet() == flags.NoMin ||
flags.getLowestSet() > j );
ls = flags.getLowestSet();
}
if ( hs == j ) {
GBASSERT( flags.getHighestSet() == flags.NoMax ||
flags.getHighestSet() < j );
hs = flags.getHighestSet();
}
//log(LOG_DEBUG, "AWL: unset j:%"INT32" wasSet:%d set:%"INT32", cnt:%"INT32"",
// j, wasSet, flags.getNumSet(), cnt);
GBASSERT( ! flags.getFlag( j ) );
GBASSERT( flags.getNumSet() == cnt );
GBASSERT( flags.getNumFlags() == TESTCASESIZE );
if ( cnt > 0 )
GBASSERT( flags.getHighestSet() >= flags.getLowestSet() );
else {
ls = flags.NoMin;
hs = flags.NoMax;
}
GBASSERT( flags.getLowestSet() == ls );
GBASSERT( flags.getHighestSet() == hs );
}
}
flags.reset();
GBASSERT( flags.getNumFlags() == TESTCASESIZE );
GBASSERT( flags.getHighestSet() == flags.NoMax );
GBASSERT( flags.getLowestSet() == flags.NoMin );
GBASSERT( flags.getNumSet() == 0 );
for ( int32_t i = 0; i < flags.getNumFlags(); i++ ) {
GBASSERT( ! flags.getFlag( i ) );
}
timer.stop();
log("AWL: Flags %"INT32" tests took %lld ms", TESTCASESIZE, timer.getSpan());
log(LOG_DEBUG, "AWL: Flags tests passed. :)");
}