void Check( AtomicByte array[], size_t n, size_t expected_size ) { if( expected_size ) for( size_t k=0; k<n; ++k ) { if( array[k] != int(UseKey(k)) ) { REPORT("array[%d]=%d != %d=UseKey(%d)\n", int(k), int(array[k]), int(UseKey(k)), int(k)); ASSERT(false,NULL); } } }
void TestInsertFindErase( int nthread ) { int n=250000; // compute m = number of unique keys int m = 0; for( int i=0; i<n; ++i ) m += UseKey(i); MyAllocator a; a.items_freed = a.frees = 100; ASSERT( MyDataCount==0, NULL ); MyTable table(a); TraverseTable(table,n,0); ParallelTraverseTable(table,n,0); CheckAllocator(table, 0, 100); DoConcurrentOperations<Insert,MyTable>(table,n,"insert",nthread); ASSERT( MyDataCount==m, NULL ); TraverseTable(table,n,m); ParallelTraverseTable(table,n,m); CheckAllocator(table, m, 100); DoConcurrentOperations<Find,MyTable>(table,n,"find",nthread); ASSERT( MyDataCount==m, NULL ); CheckAllocator(table, m, 100); DoConcurrentOperations<FindConst,MyTable>(table,n,"find(const)",nthread); ASSERT( MyDataCount==m, NULL ); CheckAllocator(table, m, 100); EraseCount=0; DoConcurrentOperations<Erase,MyTable>(table,n,"erase",nthread); ASSERT( EraseCount==m, NULL ); ASSERT( MyDataCount==0, NULL ); TraverseTable(table,n,0); CheckAllocator(table, m, m+100); bad_hashing = true; table.clear(); bad_hashing = false; if(nthread > 1) { YourTable ie_table; for( int i=0; i<IE_SIZE; ++i ) InsertEraseCount[i] = 0; DoConcurrentOperations<InsertErase,YourTable>(ie_table,n/2,"insert_erase",nthread); for( int i=0; i<IE_SIZE; ++i ) ASSERT( InsertEraseCount[i]==ie_table.count(MyKey::make(i)), NULL ); DoConcurrentOperations<InnerInsert,YourTable>(ie_table,2000,"inner insert",nthread); Harness::SpinBarrier barrier(nthread); REMARK("testing erase on fake exclusive accessor\n"); NativeParallelFor( nthread, FakeExclusive(barrier, ie_table)); } }
static void apply( MyTable& table, int i ) { MyTable::accessor a; const MyTable::accessor& ca = a; bool b = table.find( a, MyKey::make(i) ); ASSERT( b==!a.empty(), NULL ); if( b ) { if( !UseKey(i) ) REPORT("Line %d: unexpected key %d present\n",__LINE__,i); AssertSameType( &*a, static_cast<MyTable::value_type*>(0) ); ASSERT( ca->second.value_of()==i*i, NULL ); ASSERT( (*ca).second.value_of()==i*i, NULL ); if( i&1 ) ca->second.set_value( ~ca->second.value_of() ); else (*ca).second.set_value( ~ca->second.value_of() ); } else { if( UseKey(i) ) REPORT("Line %d: key %d missing\n",__LINE__,i); } }
static void apply( const MyTable& table, int i ) { MyTable::const_accessor a; const MyTable::const_accessor& ca = a; bool b = table.find( a, MyKey::make(i) ); ASSERT( b==(table.count(MyKey::make(i))>0), NULL ); ASSERT( b==!a.empty(), NULL ); ASSERT( b==UseKey(i), NULL ); if( b ) { AssertSameType( &*ca, static_cast<const MyTable::value_type*>(0) ); ASSERT( ca->second.value_of()==~(i*i), NULL ); ASSERT( (*ca).second.value_of()==~(i*i), NULL ); } }
void AskAll(KEY leftKey, RELATION id, void (*UseKey) (void *)) { register struct relationDef *rd = FindRelation(id); if (rd && CompareKey) { register struct relation *r; for (r = rd->rd_relationsTable; r; r = r->r_next) { if (CompareKey(r->r_leftKey, leftKey)) { if (UseKey) UseKey(r->r_rightKey); } } } }
static void apply( MyTable& table, int i ) { if( UseKey(i) ) { if( i&4 ) { MyTable::accessor a; table.insert( a, MyKey::make(i) ); if( i&1 ) (*a).second.set_value(i*i); else a->second.set_value(i*i); } else if( i&1 ) { MyTable::accessor a; table.insert( a, std::make_pair(MyKey::make(i), MyData(i*i)) ); ASSERT( (*a).second.value_of()==i*i, NULL ); } else { MyTable::const_accessor ca; table.insert( ca, std::make_pair(MyKey::make(i), MyData(i*i)) ); ASSERT( ca->second.value_of()==i*i, NULL ); } } }
//! Test traversing the table with an iterator. void TraverseTable( MyTable& table, size_t n, size_t expected_size ) { REMARK("testing traversal\n"); size_t actual_size = table.size(); ASSERT( actual_size==expected_size, NULL ); size_t count = 0; bool* array = new bool[n]; memset( array, 0, n*sizeof(bool) ); const MyTable& const_table = table; MyTable::const_iterator ci = const_table.begin(); for( MyTable::iterator i = table.begin(); i!=table.end(); ++i ) { // Check iterator int k = i->first.value_of(); ASSERT( UseKey(k), NULL ); ASSERT( (*i).first.value_of()==k, NULL ); ASSERT( 0<=k && size_t(k)<n, "out of bounds key" ); ASSERT( !array[k], "duplicate key" ); array[k] = true; ++count; // Check lower/upper bounds std::pair<MyTable::iterator, MyTable::iterator> er = table.equal_range(i->first); std::pair<MyTable::const_iterator, MyTable::const_iterator> cer = const_table.equal_range(i->first); ASSERT(cer.first == er.first && cer.second == er.second, NULL); ASSERT(cer.first == i, NULL); ASSERT(std::distance(cer.first, cer.second) == 1, NULL); // Check const_iterator MyTable::const_iterator cic = ci++; ASSERT( cic->first.value_of()==k, NULL ); ASSERT( (*cic).first.value_of()==k, NULL ); } ASSERT( ci==const_table.end(), NULL ); delete[] array; if( count!=expected_size ) { REPORT("Line %d: count=%ld but should be %ld\n",__LINE__,long(count),long(expected_size)); } }
void UnSetAll(KEY key, void (*UseKey) (KEY)) { register struct relationDef *rd; for (rd = relationsDefBase; rd; rd = rd->rd_next) { register struct relation *r; register struct relation **h; h = &rd->rd_relationsTable; for (r = rd->rd_relationsTable; r; r = r->r_next) { if (CompareKey(r->r_leftKey, key) || CompareKey(r->r_rightKey, key)) { if (UseKey) UseKey(key); *h = r->r_next; TCFreeMem(r, sizeof(*r)); } h = &r->r_next; } } }