void search_main(search_result *mainresult, search_problem *mainproblem) { search_problem problem; search_configuration conf; search_result result; /* check parameters */ ASSERT(mainresult != (search_result *)0); ASSERT(mainproblem != (search_problem *)0); /* initialize search configuration */ conf.numthreads = 4; /* branch: different search modes */ switch (mainproblem->mode) { case SEARCH_MODE_NONE: { /* nothing to do */ break; } case SEARCH_MODE_DEPTH: { /* initalize search configuration */ conf.problem = mainproblem; conf.result = mainresult; /* execute the search */ search_basic(&conf); /* that is it */ break; } case SEARCH_MODE_DEPTH_FULL: { /* initalize search configuration */ conf.problem = mainproblem; conf.result = mainresult; /* execute the search */ search_basic(&conf); /* check if an interesting result was found */ if (mainresult->rating != RATING_INIT_INF) { /* check if result is incomplete */ if ((int)ML_SIZE(mainresult->solution) < RATING_MOVES_TILL_MATE(mainresult->rating)) { /* create local copies of problem and result */ memcpy(&problem, mainproblem, sizeof(search_problem)); memcpy(&result, mainresult, sizeof(search_result)); /* initalize search configuration */ conf.problem = &problem; conf.result = &result; /* continue search until result is complete */ while ((int)ML_SIZE(mainresult->solution) < RATING_MOVES_TILL_MATE(mainresult->rating)) { /* decrease search depth and adapt precalculation depth */ problem.depth -= ML_SIZE(result.solution); /* transfer current solution moves to problem */ ML_APPLY(problem.pos, result.solution); ML_CLEAR(result.solution); /* initiate new search */ search_basic(&conf); /* transfer result */ ML_COPY(mainresult->solution, result.solution); } } } /* that is it */ break; } default: { /* not implemented or invalid search */ ASSERT(0); } } }
void CN_CONNECTIVITY_ALGO::searchConnections() { #ifdef CONNECTIVITY_DEBUG printf("Search start\n"); #endif #ifdef PROFILE PROF_COUNTER garbage_collection( "garbage-collection" ); #endif std::vector<CN_ITEM*> garbage; garbage.reserve( 1024 ); m_itemList.RemoveInvalidItems( garbage ); for( auto item : garbage ) delete item; #ifdef PROFILE garbage_collection.Show(); PROF_COUNTER search_basic( "search-basic" ); #endif std::vector<CN_ITEM*> dirtyItems; std::copy_if( m_itemList.begin(), m_itemList.end(), std::back_inserter( dirtyItems ), [] ( CN_ITEM* aItem ) { return aItem->Dirty(); } ); if( m_progressReporter ) { m_progressReporter->SetMaxProgress( dirtyItems.size() ); m_progressReporter->KeepRefreshing(); } if( m_itemList.IsDirty() ) { size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(), ( dirtyItems.size() + 7 ) / 8 ); std::atomic<size_t> nextItem( 0 ); std::vector<std::future<size_t>> returns( parallelThreadCount ); auto conn_lambda = [&nextItem, &dirtyItems] ( CN_LIST* aItemList, PROGRESS_REPORTER* aReporter) -> size_t { for( size_t i = nextItem++; i < dirtyItems.size(); i = nextItem++ ) { CN_VISITOR visitor( dirtyItems[i] ); aItemList->FindNearby( dirtyItems[i], visitor ); if( aReporter ) aReporter->AdvanceProgress(); } return 1; }; if( parallelThreadCount <= 1 ) conn_lambda( &m_itemList, m_progressReporter ); else { for( size_t ii = 0; ii < parallelThreadCount; ++ii ) returns[ii] = std::async( std::launch::async, conn_lambda, &m_itemList, m_progressReporter ); for( size_t ii = 0; ii < parallelThreadCount; ++ii ) { // Here we balance returns with a 100ms timeout to allow UI updating std::future_status status; do { if( m_progressReporter ) m_progressReporter->KeepRefreshing(); status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) ); } while( status != std::future_status::ready ); } } if( m_progressReporter ) m_progressReporter->KeepRefreshing(); } #ifdef PROFILE search_basic.Show(); #endif m_itemList.ClearDirtyFlags(); #ifdef CONNECTIVITY_DEBUG printf("Search end\n"); #endif }