Exemple #1
0
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

}