繁体   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