#include "threadpool/atomic_list.h" #include "common/UnitTest.h" #include "common/Utilities.h" #include #include #include #include #include #include #include #include #include #include static void modify_list( AtomicList& list ) { const int N_count = 50000; for (int i=0; i=(rand()/8); } ); auto v4 = list.remove( [](int v) { return v>=(rand()/4); } ); auto v5 = list.remove( [](int v) { return v>=(rand()/2); } ); if ( v1 !=-1 ) { list.insert( v1 ); } if ( v2 !=-1 ) { list.insert( v2 ); } if ( v3 !=-1 ) { list.insert( v3 ); } if ( v4 !=-1 ) { list.insert( v4 ); } if ( v5 !=-1 ) { list.insert( v5 ); } } } static bool check_list( const std::vector& x, AtomicList& list ) { bool pass = list.check(); pass = pass && (int) x.size() == list.size(); if ( pass ) { for (size_t i=0; i& list ) { for (int i=0; i list(-1); if ( list.size()==0 && list.check() ) ut.passes( "Initialize" ); else ut.failure( "Initialize" ); // Initialize the list with some empty values for (int i=0; i<80; i++) list.insert( rand() ); list.insert( 2 ); list.insert( 1 ); list.insert( rand() ); // Try to pull off a couple of values int v1 = list.remove( [](int a) { return a==1; } ); // Find the entry with 1 int v2 = list.remove( [](int) { return true; } ); // Get the first entry int v3 = list.remove( [](int) { return false; } ); // Fail to get an entry if ( v1==1 && v2==2 && v3==-1 && list.size()==81 && list.check() ) ut.passes( "Basic sanity test" ); else ut.failure( "Basic sanity test" ); // Clear the list while ( list.remove( [](int) { return true; } ) != -1 ) {} // Create a list of known values //std::vector data0(512); std::vector data0(5*N_threads); for (size_t i=0; i time; std::chrono::time_point start, stop; time = time.zero(); for (int it=0; it(stop-start).count(); int64_t N1 = list.N_remove(); bool pass = check_list( data, list ); if ( pass ) ut.passes( "Serial get/insert" ); else ut.failure( "Serial get/insert" ); printf("serial time = %0.5f s\n",time_serial); printf("serial time/item = %0.0f ns\n",1e9*time_serial/(N1-N0)); // Have multiple threads reading/writing to the list simultaneously std::vector threads( N_threads ); start = std::chrono::high_resolution_clock::now(); for ( int i = 0; i < N_threads; i++ ) threads[i] = std::thread( modify_list, std::ref(list) ); for ( int i = 0; i < N_threads; i++ ) threads[i].join(); stop = std::chrono::high_resolution_clock::now(); double time_parallel = std::chrono::duration(stop-start).count(); int64_t N2 = list.N_remove(); pass = check_list( data, list ); if ( pass ) ut.passes( "Parallel get/insert" ); else ut.failure( "Parallel get/insert" ); printf("parallel time = %0.5f s\n",time_parallel); printf("parallel time/item = %0.0f ns\n",1e9*time_parallel/(N2-N1)); // Try to over-fill the list while ( !list.empty() ) list.remove_first(); for (int i=1; i<=list.capacity(); i++) list.insert( i ); try { list.insert( list.capacity()+1 ); ut.failure( "List overflow" ); } catch (const std::exception& e) { ut.passes( "List overflow" ); } catch(...) { ut.failure( "List overflow (unknown exception)" ); } // Finished ut.report(); int N_errors = static_cast( ut.NumFailGlobal() ); return N_errors; }