0

指定された拡張子のファイルを検索して正規表現に一致するものを探すために、スレッドプールを利用するプログラムを作成しています。

私のスレッドプールは次のようになります。

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内のすべての項目が完了していることを確認する必要があります。どんな考えでも本当にありがたいです。

4

2 に答える 2

1

一致するファイルの再帰的なファイルシステム検索を実行する専用のスレッド (おそらくファイル処理スレッドを生成する同じスレッド) を 1 つ持つことをお勧めします。ファイルを検索スレッドが作業を取得できる作業キューにファイルを追加できます。条件変数を使用してこれを調整できます。

あなたが見つけたように、シャットダウンの調整は少し難しいです。ファイルシステム検索スレッドが検索を完了した後、ワーカー スレッドに表示される「キューに入れられたものを終了する」フラグを設定し、すべてのワーカー スレッドを起動して別のファイルの処理を試みるように通知できます。彼らは終了します。次に、ファイルシステム検索スレッドがすべてのワーカーに参加します。

于 2012-08-16T02:55:30.750 に答える
0

Tony の回答のコメントにある更新された質問については、2 種類のタスクを用意することをお勧めします。1 つはサブディレクトリを再帰的に探索するためのもので、もう 1 つは grep のためのものです。SynQueue<TaskBase>、、TaskSubDir: TaskBaseおよびが必要ですTaskGrep: TaskBaseTaskBaseには仮想インターフェース機能がありますRun()。その後、スレッドは から繰り返しポップしSynQueue、 を呼び出しますTaskBase::Run()

  1. を取得した場合TaskSubDir、指定されたパスでサブディレクトリとファイルを検索します。(a) フォルダーの場合は、新しいTaskSubDirサブディレクトリを に追加SynQueueし、フォルダーがスレッドプールで再帰的に検索されるようにします。(b) 拡張子が一致するファイルの場合、a を にプッシュTaskGrepSynQueueます。
  2. を取得した場合TaskGrep、 を実行しSearchFileます。
  3. キューが空の場合はbreak、ワーカー関数から除外されます。

そうすることで、2 つのキューを持つ必要がなくなり、grep キューを開始する前にサブディレクトリ キューが終了するのを待つ必要がなくなります。

あなたの質問に答えると、参加条件を判断するには、すべてのスレッドがbreakワーカー関数から出るのを待つだけです。

最後の注意:_tasks.empty()コードの最初の部分はミューテックスによって保護されておらず、競合状態になる可能性があります。クラス内のミューテックスと cond_var を非表示にして、(ミューテックスで保護された) メンバー関数SynQueueを追加することをお勧めします。効率が重要な場合は、ロックフリー キューを置き換えることSynQueue::empty()を検討してください。SynQueue

于 2012-08-16T04:04:53.703 に答える