簡體   English   中英

std :: mutex和condition_variable無法訪問類中的私有成員

[英]std::mutex and condition_variable cannot access private member inside class

我已經做了一些谷歌搜索並看到關於這個問題的堆棧溢出的類似問題,但我很難理解處理它的原因/解決方案。 鑒於在ThreadPool.hpp中聲明的以下類,我收到以下2個錯誤:

錯誤1錯誤C2248:'std :: mutex :: mutex':無法訪問類'std :: mutex'中聲明的私有成員c:\\ users \\ jesse \\ documents \\ school \\ summer semester 2012 \\ concurrent processing \\ project 2 \\ ultra_grep v2 \\ ultra_grep \\ threadpool.hpp 39 1 ultra_grep2

錯誤2錯誤C2248:'std :: condition_variable :: condition_variable':無法訪問在類'std :: condition_variable'中聲明的私有成員c:\\ users \\ jesse \\ documents \\ school \\ summer semester 2012 \\ concurrent processing \\ project 2 \\ ultra_grep v2 \\ ultra_grep \\ threadpool.hpp 39 1 ultra_grep2

class ThreadPool
{
private:
std::queue<std::string> _consoleTasks;
std::queue<std::tr2::sys::path> _tasks;
std::map<std::string, std::vector<GrepMatch>> _grepMatches;
int _nThreads, _fileMatches, _totalMatches, _workingThreads;
std::vector<thread> _threads;
Arguments _args;
std::mutex _taskMutex, _wakeMutex, _consoleMutex, _threadCountMutex;
std::condition_variable _wakeCondition;

public:
ThreadPool( int threads, Arguments args );
~ThreadPool() {};
void GrepFunc();
void ConsoleFunc();
void SearchFile( std::string );
void SearchFileVerbose( std::string );
void DisplayGrepResults();

queue<std::tr2::sys::path> Tasks() { return _tasks; }

};

以及在ThreadPool.cpp中實現的代碼:

#include "ThreadPool.hpp"

using namespace std;
namespace fs = std::tr2::sys;

ThreadPool::ThreadPool( int threads, Arguments args )
: _nThreads( threads ), _args( args ), _fileMatches( 0 ), _totalMatches( 0 ), _workingThreads( 0 )
{

for( int i = 0; i < _nThreads; ++i )
{
        _threads.push_back( thread( &ThreadPool::GrepFunc, this ) );
        _tasks.push( args.root() );
        ++_workingThreads;
        _wakeCondition.notify_one();
}

for( auto& t : _threads )
{
    t.join();
}

DisplayGrepResults();
}

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

while( !_workingThreads )
{
    { unique_lock<mutex> lk( _wakeMutex );
    _wakeCondition.wait( lk ); }

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

        if( gotTask )
        {
            if( fs::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() ); }
                        _wakeCondition.notify_one();
                    }
                    else
                    {
                        for( auto& e : _args.extensions() )
                        {
                            if( !dirIter->path().extension().compare( e ) )
                            {
                                { lock_guard<mutex> tl( _taskMutex );
                                _tasks.push( dirIter->path() ); }
                                _wakeCondition.notify_one();
                                //SearchFile( dirIter->path() );
                            }
                        }
                    }
                }
            }
            else
            {
                for( auto& e : _args.extensions() )
                {
                    if( !task.extension().compare( e ) )
                    {
                        if( _args.is_verbose() )
                            SearchFile( task );
                        else
                            SearchFileVerbose( task );
                    }
                }
            }

            { lock_guard<mutex> tc( _threadCountMutex) ;
            --_workingThreads; }
        }
    }
}
}

void ThreadPool::SearchFileVerbose( string path )
{
fstream file;
file.open( path );

if( !file )
{
    // error handling
}
else
{
    { 
        lock_guard<mutex> cm( _consoleMutex );
        cout << "\nGrepping: " << path << endl;

        int lineNumber = 1;
        string line;
        vector<GrepMatch> matches;
        while( getline( file, line ) )
        {
            int lineMatches = 0;
            sregex_token_iterator end;
            for (sregex_token_iterator i(line.cbegin(), line.cend(), _args.regular_expression() );
                i != end;
                ++i)
            {
                ++lineMatches;
            }

            if( lineMatches > 0 )
            {
                GrepMatch match = GrepMatch( lineNumber, lineMatches, line );
                matches.push_back( match );
                cout << "Matched " << lineMatches << ": " << path << " [" << lineNumber << "] " << line << endl; 
            }

            ++lineNumber;
        }

        if( !matches.empty() )
        {
            _grepMatches[ path ] = matches;
        }
    }
}
}

我在互斥鎖和condition_variable上都遇到錯誤,說他們無法訪問在類中聲明的私有成員。 我的理解是,這是指復制構造函數? 雖然我不明白為什么會發揮作用,因為我不知道我在哪里制作副本,因為他們只是班上的私人成員。

根據初始注釋,我只實例化一個ThreadPool實例,並且不會在任何地方復制。 我試圖觸摸互斥鎖的唯一一次是在我班級的.cpp實現中。

任何人都可以幫助我更好地理解為什么會這樣嗎?

對於那些感興趣的人是編譯器輸出:

1>------ Build started: Project: ultra_grep2, Configuration: Debug Win32 ------
1>  ultra_grep_main.cpp
1>  Unknown compiler version - please run the configure tests and report the results
1>c:\users\jesse\documents\school\summer semester 2012\concurrent processing\project 2\ultra_grep v2\ultra_grep\threadpool.hpp(39): error C2248: 'std::mutex::mutex' : cannot access private member declared in class 'std::mutex'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\mutex(116) : see declaration of 'std::mutex::mutex'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\mutex(107) : see declaration of 'std::mutex'
1>          This diagnostic occurred in the compiler generated function 'ThreadPool::ThreadPool(const ThreadPool &)'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\mutex(116) : see declaration of 'std::mutex::mutex'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\mutex(107) : see declaration of 'std::mutex'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\mutex(116) : see declaration of 'std::mutex::mutex'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\mutex(107) : see declaration of 'std::mutex'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\mutex(116) : see declaration of 'std::mutex::mutex'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\mutex(107) : see declaration of 'std::mutex'
1>c:\users\jesse\documents\school\summer semester 2012\concurrent processing\project 2\ultra_grep v2\ultra_grep\threadpool.hpp(39): error C2248: 'std::condition_variable::condition_variable' : cannot access private member declared in class 'std::condition_variable'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\condition_variable(45) : see declaration of 'std::condition_variable::condition_variable'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\condition_variable(30) : see declaration of 'std::condition_variable'
1>          This diagnostic occurred in the compiler generated function 'ThreadPool::ThreadPool(const ThreadPool &)'
1>  ThreadPool.cpp
1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

問題是你的想法; 編譯器生成的復制構造函數和賦值運算符失敗,因為mutex和condition_variable不可復制。 在許多情況下,編譯器仍會為這兩者生成代碼,即使您沒有故意調用它們也不容易看到。 根據我的經驗,這個錯誤通常是由於嘗試將類型與標准庫容器一起使用而引起的。

你應該添加一個空的私有拷貝構造函數和賦值運算符,即使你沒有這個問題; 我認為嘗試復制線程池是不可取的。

錯誤在某處:

1> ultra_grep_main.cpp

使用 ThreadPool的復制構造函數:

這個診斷發生在編譯器生成的函數'ThreadPool :: ThreadPool(const ThreadPool&)'中

我真的很驚訝編譯器沒有指出源文件中的哪一行隱式生成了復制構造函數。

在評論中,您詢問復制構造函數應該如何。 一個更好的問題是,制作一個ThreadPool對象的副本是否有意義,答案是一般情況下它沒有。 要改進錯誤消息,您可以將復制構造函數標記為deleted ,這樣(希望)編譯器將生成更好的錯誤報告,指出需要復制的位置:

class ThreadPool {
   ThreadPool( ThreadPool const & ) = delete;
// ...
};

如果您的編譯器不支持此C ++ 11功能,則替代方法是聲明復制構造函數但不定義它。 這將在復制構造函數的使用位置觸發訪問錯誤。

暫無
暫無

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

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