簡體   English   中英

線程池的C ++ std :: thread停止條件

[英]C++ std::thread stopping condition for thread pool

我正在編寫一個利用線程池的程序,以便在指定擴展名的文件中搜索正則表達式的匹配項。

我的線程池如下所示:

for( int i = 0; i < _nThreads; ++i )
    {
            _threads.push_back( thread( &ThreadPool::GrepFunc, this ) );
    }

運行函數如下所示:

void ThreadPool::GrepFunc()
{
    // implement a barrier

while( !_done )
{
    while( !_tasks.empty() )
    {
        fs::path task;
        bool gotTask = false;
        {
            lock_guard<mutex> tl( _taskMutex );
            if( !_tasks.empty() )
            {
                task = _tasks.front();
                _tasks.pop();
                gotTask = true;
            }
        }

        if( gotTask )
        {
            if( std::tr2::sys::is_directory( task ) )
            {
                for( fs::directory_iterator dirIter( task ), endIter; dirIter != endIter; ++dirIter )
                {
                    if( fs::is_directory( dirIter->path() ) )
                    {
                        { lock_guard<mutex> tl( _taskMutex );
                        _tasks.push( dirIter->path() ); }
                    }
                    else
                    {
                        for( auto& e : _args.extensions() )
                        {
                            if( !dirIter->path().extension().compare( e ) )
                            {
                                SearchFile( dirIter->path() );
                            }
                        }
                    }
                }
            }
            else
            {
                for( auto& e : _args.extensions() )
                {
                    if( !task.extension().compare( e ) )
                    {
                        SearchFile( task );
                    }
                }
            }
        }
    }
}
}

從本質上講,該程序從用戶那里接收一個初始目錄,並將在該目錄和所有子目錄中遞歸搜索與擴展名匹配的文件,以查找正則表達式匹配項。 我在弄清楚如何確定到達_done時的停止情況時遇到了麻煩。 我需要確保初始目錄中的所有目錄和文件都已被掃描,並且_tasks中的所有項都已完成,然后再加入線程。 任何想法將不勝感激。

我建議有一個線程(可能是產生文件處理線程的同一線程)專用於對匹配文件進行遞歸文件系統搜索。 它可以將文件添加到工作隊列中,文件搜索線程可以從中獲取工作。 您可以使用條件變量來對此進行協調。

如您所見,協調關機有點棘手。 在文件系統搜索線程完成搜索之后,它可以設置一些對工作線程可見的“僅完成隊列中的內容”標志,然后向所有人發出信號以喚醒它們並嘗試處理另一個文件:如果它們發現文件/工作隊列為空他們退出。 然后,文件系統搜索線程加入所有工作程序。

關於您在Tony的答案評論中更新的問題,我建議執行2種任務:一項用於遞歸地瀏覽子目錄,另一項用於grep。 您需要一個SynQueue<TaskBase>TaskSubDir: TaskBaseTaskGrep: TaskBase TaskBase具有虛擬接口functon Run() 然后線程可以從SynQueue反復彈出,並調用TaskBase::Run()

  1. 如果它有一個TaskSubDir ,那么它將在給定路徑中找到子目錄和文件:(a)如果它是一個文件夾,則將該子目錄的新TaskSubDir添加到SynQueue ,以便使用線程池 (b)如果它是具有匹配擴展名的文件,則它將TaskGrep推送到SynQueue
  2. 如果有TaskGrep ,則執行SearchFile
  3. 如果隊列為空,請break worker函數。

這樣做,您不需要有2個隊列並等待子目錄隊列完成才可以啟動grep隊列。

所以回答你的問題:確定加盟條件下,所有你需要做的是等待所有線程break了工人的功能。

最后說明:代碼中的第一個_tasks.empty()不受互斥量保護,並且可能會出現競爭狀況。 我建議您在SynQueue類中隱藏互斥鎖和cond_var,並添加一個SynQueue::empty()成員函數(受互斥鎖保護)。 如果您關注效率,則可能要考慮使用無鎖隊列來代替SynQueue

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM