boost ::线程执行

时间:2013-04-09 16:17:33

标签: multithreading boost mutex halt

我有一个类ChunkManager,它有一些(应该是)异步方法。这些方法处理我的游戏引擎中的任务,例如在不同的线程上加载地图块(类似于Minecraft),以便不完全停止主线程(它们是冗长的操作) 以下是其中一种方法:

void ChunkManager::asyncRenderChunks(){

    boost::thread loadingThread(&ChunkManager::renderChunks,this);
}

renderChunks的样子:

void ChunkManager::renderChunks(){
activeChunksMutex->lock();
      for(int z=0; z < CHUNK_MAX; z=z+1)
      {
        for(int y=0; y < CHUNK_MAX; y=y+1)
        {
            for(int x=0; x < CHUNK_MAX; x=x+1)
            {

            activeChunks[x][y][z]->Render(scnMgr);

            }
        }
    }
    activeChunksMutex->unlock();
}

这应该有用,对吗?然而,当它运行时它会崩溃。我有一种感觉,它与我在线程创建后对线程的处理有关,因为如果我放了

  

loadingThread.join();

在前面提到的方法中,它工作正常,但主线程停止了,因为很明显它只是等待新线程完成,有效地让我回到原点。 有什么建议? 对不起,如果这是一个迟钝的问题,我是线程概念的新手。 感谢。

更新(2013年4月9日): 我找到了这个宝石:http://threadpool.sourceforge.net/ ..并解决了我的问题!

2 个答案:

答案 0 :(得分:0)

如果您可以加入该主题,那么它必须是可加入的。

正如in the documentation所述:

  

当代表执行线程的boost::thread对象被销毁时,如果线程可加入,程序将终止。

您创建了一个本地thread对象,立即让它超出范围:ChunkManager::asyncRenderChunks返回时它被销毁。

或者:

  • 使其成为分离(不可连接)的线程

    void ChunkManager::asyncRenderChunks() {
        boost::thread loadingThread(&ChunkManager::renderChunks,this);
        loadingThread.detach();
    }
    
  • 或在其他地方创建thread对象并保持活着

    class ChunkManager {
        boost::thread renderingThread;
        bool renderChunkWork;       // work to do flag
        Chunk activeChunks[CHUNK_MAX][CHUNK_MAX][CHUNK_MAX];
        boost::mutex activeChunksMutex;
        boost::condition_variable activeChunksCV;
    
        bool shutdown;              // shutdown flag
    
        void renderChunks() {
            for(int z=0; z < CHUNK_MAX; ++z)
                for(int y=0; y < CHUNK_MAX; ++y)
                    for(int x=0; x < CHUNK_MAX; ++x)
                        activeChunks[x][y][z]->Render(scnMgr);
        }
    
        void renderChunkThread() {
            boost::unique_lock<boost::mutex> guard(activeChunksMutex);
            while (true) {
                while (!(renderChunkWork || shutdown))
                    activeChunksCV.wait(guard);
    
                if (shutdown)
                    break;
                renderChunks();
                doRenderChunks = false;
            }
        }
    
    public:
        ChunkManager()
            : loadingThread(&ChunkManager::renderChunkThread, this),
            renderChunkWork(false), shutdown(false)
        {}
    
        ~ChunkManager() {
            { // tell the rendering thread to quit
                boost::unique_lock<boost::mutex> guard(activeChunksMutex);
                renderChunkShutdown = true;
                activeChunksCV.notify_one();
            }
            renderingThread.join()
        }
    
        void asyncRenderChunks() {
            boost::unique_lock<boost::mutex> guard(activeChunksMutex);
            if (!renderChunkWork) {
                renderChunkWork = true;
                activeChunksCV.notify_one();
            }
        }
    };
    

NB。一般来说,即时创建线程并不比预先创建线程好,只是在有事情要做时唤醒它们。它避免了在最后一个调用完成之前如何处理对asyncRenderChunks的第二次调用(启动第二个线程?块?),并移动与线程创建相关的延迟。


关于对象生存期的注意事项

在这段代码中意识到这一点非常重要:

void ChunkManager::asyncRenderChunks() {
    SomeType myObject;
}

将创建实例myObject ,然后立即销毁

答案 1 :(得分:0)

崩溃,因为在当前版本的Boost.Thread中,您必须加入()一个主题或detach() - 否则~thread would terminate the program。 (在早期版本中~thread用于自动调用detach()。)

因此,如果您不想加入该主题 - 只需将其分开:

boost::thread loadingThread(&ChunkManager::renderChunks,this);
loadingThread.detach();