Reputation: 21147
I have done some googling and seen similar questions on stack overflow regarding this issue but am having trouble understanding the cause/solution to deal with it. Given the following class which is declared in ThreadPool.hpp I am getting the following 2 errors:
Error 1 error C2248: 'std::mutex::mutex' : cannot access private member declared in class '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
Error 2 error C2248: 'std::condition_variable::condition_variable' : cannot access private member declared in class '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; }
};
and the code that is implemented inside of 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;
}
}
}
}
I am getting errors on both the mutex and the condition_variable saying that they cannot access private members declared inside the class. It is my understanding that this is referring to the copy constructor? Although I don't understand why that comes into play cause I don't see where I am trying to make a copy as they are simply private members of the class.
As per the initial comments I only instantiate a single instance of ThreadPool and it is not copied anywhere. The only times I am trying to touch the mutexes at all are in the .cpp implementation of my class.
Can anyone help me gain a better understanding of why this is happening?
For those interested here is the compiler output:
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 ==========
Upvotes: 2
Views: 4654
Reputation: 208353
The error is somewhere in:
1> ultra_grep_main.cpp
where the copy constructor of ThreadPool
is used:
This diagnostic occurred in the compiler generated function 'ThreadPool::ThreadPool(const ThreadPool &)'
I am actually surprised that the compiler did not point at what line in the source file the copy constructor is implicitly generated.
In a comment you ask how the copy constructor should look like. A better question is whether it makes sense to make copies of a ThreadPool
object, and the answer is that in general it doesn't. To improve the error message you could mark the copy constructor as deleted
, and that way (hopefully) the compiler will produce better error reports as to where the copy is needed:
class ThreadPool {
ThreadPool( ThreadPool const & ) = delete;
// ...
};
If your compiler does not support this C++11 feature, the alternative is to declare the copy constructor but not define it. That will trigger an access error at the place of use of the copy constructor.
Upvotes: 3
Reputation: 13993
The problem is what you thought; the compiler-generated copy constructor and assignment operator are failing, because mutex and condition_variable aren't copyable. The compiler still generates code for both in many cases that aren't easy to see, even though you aren't intentionally invoking them. In my experience, this error is usually caused by trying to use the type with a standard library container.
You should probably add an empty private copy constructor and assignment operator, even if you didn't have this issue; I don't think it's ever desirable to try to copy a thread pool.
Upvotes: 7