Данная программа если ее собрать вот так: g++ test_boost_threading.cpp -g -lboost_thread-mt и запустить вот так: ./a.out 2 у меня сегфолтится. В чем дело не пойму. Это часть несколько большей программы которая ищет выход из лабиринта. Многопоточность нужна для ускорения, когда подлабиринты обрабатываются в отдельных потоках. Но пока что оно на количестве потоков начиная с 2-х ловит сегфолт.
#include <iostream>
#include <deque>
#include "boost/thread.hpp"
class TaskThreadedSolver;
class TaskStub
{
public:
TaskStub( TaskThreadedSolver& manager ) : m_manager(manager), m_length(0)
{}
void solve();
private:
TaskThreadedSolver& m_manager;
int m_length;
};
class SolverThread
{
public:
SolverThread( TaskThreadedSolver& param ) : m_pool(param)
{}
void operator()();
private:
TaskThreadedSolver& m_pool;
};
class TaskThreadedSolver
{
public:
TaskThreadedSolver( int threadCount ) : m_threadCount(threadCount),
m_workThreadCount(0),
m_threadControl( TaskThreadedSolver::lets_wait )
{
SolverThread thread_struct(*this);
for( int i = 0; i < m_threadCount; ++i )
{
m_threads.add_thread( new boost::thread( thread_struct ) );
}
}
void solve()
{
TaskStub ts(*this);
m_lock.lock();
m_tasks.push_back(ts);
m_workThreadCount = 0;
m_lock.unlock();
// start work
{
boost::mutex::scoped_lock lock( m_starter );
while( m_threadControl == lets_start )
{
m_condVar.wait(lock);
}
m_threadControl = lets_start;
}
m_condVar.notify_all();
}
bool freeThreadsPresent()
{
m_lock.lock();
int nthreads = m_threadCount;
int nworking = m_workThreadCount;
m_lock.unlock();
return ( nthreads - nworking ) > 0;
}
void addTask( TaskStub tb )
{
boost::mutex::scoped_lock( m_lock );
m_tasks.push_back( tb );
}
void tryRunTask()
{
m_lock.lock();
if( m_tasks.size() == 0 )
{
m_lock.unlock();
return;
}
TaskStub task = m_tasks.front();
m_tasks.pop_front();
m_lock.unlock();
incrementWorkThreadCount();
task.solve();
decrementWorkThreadCount();
}
bool stillUndone()
{
bool ret = false;
m_lock.lock();
if( m_workThreadCount > 0 )
ret = true;
if( !ret )
ret = ( m_tasks.size() > 0 );
m_lock.unlock();
if( !ret )
{
m_starter.lock();
m_threadControl = lets_wait;
m_starter.unlock();
m_condVar.notify_all();
}
return ret;
}
private:
friend class SolverThread;
std::deque<TaskStub > m_tasks;
int m_threadCount;
int m_workThreadCount;
void incrementWorkThreadCount()
{
boost::mutex::scoped_lock( m_lock );
m_workThreadCount++;
}
void decrementWorkThreadCount()
{
boost::mutex::scoped_lock( m_lock );
m_workThreadCount--;
}
boost::mutex m_lock;
boost::mutex m_starter;
boost::condition_variable m_condVar;
enum control
{
lets_wait = 1,
lets_start = 2,
lets_terminate = 3,
};
control m_threadControl;
boost::thread_group m_threads;
};
void TaskStub::solve()
{
for( int i = m_length; i < 100; ++i, ++m_length )
{
if( i%11 == 0 )
{
if( m_manager.freeThreadsPresent() )
m_manager.addTask( TaskStub( *this ) );
}
}
}
void SolverThread::operator()()
{
while(1)
{
{
boost::mutex::scoped_lock lock( m_pool.m_starter );
while( m_pool.m_threadControl == TaskThreadedSolver::lets_wait )
{
m_pool.m_condVar.wait(lock);
}
if( m_pool.m_threadControl == TaskThreadedSolver::lets_terminate )
return;
}
m_pool.m_condVar.notify_all();
m_pool.tryRunTask();
}
}
int main(int argc, char *argv[])
{
TaskThreadedSolver solver( boost::lexical_cast<int>( argv[1] ) );
clock_t time_begin = clock();
for( int i = 0; i < 50; ++i )
{
solver.solve();
boost::xtime xt;
boost::xtime_get( &xt, boost::TIME_UTC );
xt.nsec += 50;
boost::thread::sleep( xt );
while( solver.stillUndone() )
{
xt.nsec += 100;
boost::thread::sleep( xt );
}
std::cout << "task " << i << " done" << std::endl;
}
clock_t time_end = clock();
std::cout << "total time = " << ( time_end - time_begin ) << std::endl;
}