LINUX.ORG.RU

BOOST thread не понимаю ...


0

2

Данная программа если ее собрать вот так: 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 
&#123;
public:
    TaskStub( TaskThreadedSolver& manager ) : m_manager(manager), m_length(0)
    &#123;&#125;
    
    void solve();
    
private:    
    TaskThreadedSolver& m_manager;
    int m_length;
&#125;;

class SolverThread
&#123;
public:
    SolverThread( TaskThreadedSolver& param ) : m_pool(param)
    &#123;&#125;

    void operator()();

private:
    TaskThreadedSolver& m_pool;
&#125;;

class TaskThreadedSolver
&#123;
public:
    TaskThreadedSolver( int threadCount ) : m_threadCount(threadCount),
                                            m_workThreadCount(0),
                                            m_threadControl( TaskThreadedSolver::lets_wait )
    &#123;
        SolverThread thread_struct(*this);
    
        for( int i = 0; i < m_threadCount; ++i )
        &#123;
            m_threads.add_thread( new boost::thread( thread_struct ) );
        &#125;
    &#125;
    
    void solve()
    &#123;
        TaskStub ts(*this);
    
        m_lock.lock();
            m_tasks.push_back(ts);
            m_workThreadCount = 0;
        m_lock.unlock();
        
        // start work
        &#123;
            boost::mutex::scoped_lock lock( m_starter );

            while( m_threadControl == lets_start )
            &#123;
                m_condVar.wait(lock);
            &#125;
            
            m_threadControl = lets_start;
        &#125;

        m_condVar.notify_all();
    &#125;
    
    bool freeThreadsPresent()
    &#123;
        m_lock.lock();
        int nthreads = m_threadCount;
        int nworking = m_workThreadCount;
        m_lock.unlock();
    
        return ( nthreads - nworking ) > 0;
    &#125;
    
    void addTask( TaskStub tb )
    &#123;
        boost::mutex::scoped_lock( m_lock );
        m_tasks.push_back( tb ); 
    &#125;
    
    void tryRunTask()
    &#123;
        m_lock.lock();
        
        if( m_tasks.size() == 0 )
        &#123;
            m_lock.unlock();
            return;
        &#125;
        
        TaskStub task = m_tasks.front();
        m_tasks.pop_front();
        
        m_lock.unlock();

        incrementWorkThreadCount();
        task.solve();
        decrementWorkThreadCount();
    &#125;
    
    bool stillUndone()
    &#123;
        bool ret = false;
        
        m_lock.lock();
        if( m_workThreadCount > 0 )
            ret = true;

        if( !ret )
            ret = ( m_tasks.size() > 0 );
        m_lock.unlock();
    
        if( !ret )
        &#123;
            m_starter.lock();
            m_threadControl = lets_wait;
            m_starter.unlock();

            m_condVar.notify_all();
        &#125;
        
        return ret;
    &#125;
    
private:
    friend class SolverThread;
    
    std::deque<TaskStub > m_tasks; 
    
    int m_threadCount;
    int m_workThreadCount;
    
    void incrementWorkThreadCount()
    &#123;
        boost::mutex::scoped_lock( m_lock );
        m_workThreadCount++;
    &#125;
    
    void decrementWorkThreadCount()
    &#123;
        boost::mutex::scoped_lock( m_lock );
        m_workThreadCount--;  
    &#125;
    
    boost::mutex m_lock;    
    boost::mutex m_starter;
    boost::condition_variable m_condVar;    
    
    enum control
    &#123;
        lets_wait = 1,
        lets_start = 2,
        lets_terminate = 3,
    &#125;;

    control m_threadControl;  
    
    boost::thread_group m_threads;
&#125;;

void TaskStub::solve()
&#123;
    for( int i = m_length; i < 100; ++i, ++m_length )
    &#123;
        if( i%11 == 0 )
        &#123;
            if( m_manager.freeThreadsPresent() )
                m_manager.addTask( TaskStub( *this ) );
        &#125;
    &#125;
&#125;

void SolverThread::operator()()
&#123;    
    while(1)
    &#123;
        &#123;
            boost::mutex::scoped_lock lock( m_pool.m_starter );

            while( m_pool.m_threadControl == TaskThreadedSolver::lets_wait )
            &#123;
                m_pool.m_condVar.wait(lock);
            &#125;

            if( m_pool.m_threadControl == TaskThreadedSolver::lets_terminate )
                    return;
        &#125;
        
        m_pool.m_condVar.notify_all();

        m_pool.tryRunTask();
    &#125;
&#125;

int main(int argc, char *argv&#91;&#93;)
&#123;
    TaskThreadedSolver solver( boost::lexical_cast<int>( argv&#91;1&#93; ) );
    
    clock_t time_begin = clock();
    
    for( int i = 0; i < 50; ++i )
    &#123;
        solver.solve();
                    
        boost::xtime xt;
        boost::xtime_get( &xt, boost::TIME_UTC );
                    
        xt.nsec += 50;
        boost::thread::sleep( xt );
                    
        while( solver.stillUndone() )
        &#123;
            xt.nsec += 100;
            boost::thread::sleep( xt );
        &#125;
                    
        std::cout << "task " << i << " done" << std::endl;
    &#125;
    
    clock_t time_end = clock();
    std::cout << "total time = " << ( time_end - time_begin ) << std::endl;
}
★★

Последнее исправление: mio (всего исправлений: 2)

Блин все понял

Надо было копи конструктор добавить вот такой:

[code=cpp] TaskStub( const TaskStub& ts ) : m_manager( ts.m_manager ) {} [/code]

Ссылка m_manager а то не инициализируется.

mio ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.