代码在代码块中运行完美,但在终端

时间:2015-11-07 19:12:29

标签: c++ linux multithreading terminal

我在Ubuntu上使用posix在c ++中编写了一个简单的线程池,它从Code :: Blocks开始编译并按预期运行。但是,当我从终端执行程序时,它会在第一个线程任务完成后挂起。

以下是任务对象的execute()函数中的代码:

void TestTask::execute()
{
    FILE* file;
    std::string fname = "output";
    char n = (char)m_id;
    fname+=n;
    fname+=".txt";
    file = fopen(fname.c_str(), "w");
    for (int i = 0; i < 10; i++)
    {

        fprintf(file,"Thread ID: %d, count : %d\n", m_id, i);
    }
    fclose(file);
}

如您所见,代码只是将一些数据输出到每个线程的单独文件中。

我也尝试过:

void TestTask::execute()
{
    for (int i = 0; i < 10; i++)
    {

        printf("Thread ID: %d, count : %d\n", m_id, i);
    }
}

如前所述,当项目构建并在code :: blocks中运行时,这两个版本都可以正常工作,但是当从命令行运行可执行文件时,它会挂起。

线程池代码:

ThreadPool::ThreadPool(int iNumThreads):mRunning(false), mShuttingDown(false)
{
    mThreads.resize(iNumThreads);
    if(iNumThreads > 0)
    for (int i = 0; i < iNumThreads; i++)
    {
        pthread_create(&mThreads[i], NULL, ThreadPool::ThreadFunc,(void*) this);
    }
    pthread_mutex_init(&mMemLock, NULL); //mutex' are initialised unlocked.
}

void ThreadPool::stop()
{
    pthread_mutex_lock(&mMemLock);
    mRunning = false;
    pthread_mutex_unlock(&mMemLock);
}

void ThreadPool::start()
{
    //signal all threads to wake up and start extracting tasks to execute.
    if(!mTasks.empty())
        pthread_cond_broadcast(&mConditionSignal);
    mRunning = true;
}

bool ThreadPool::shutDown()
{
    //terminate all threads, regardless of status. Brute force approach, only to be used in race conditions or major errors.
    for (size_t i = 0; i < mThreads.size();i++)
    {
        int err = pthread_cancel(mThreads[i]);
        if(err != 0)
            return false;
    }
    return true;
}
bool ThreadPool::shutDownClean()
{
    //set flag and wait for all threads to terminate normally
    mShuttingDown = true;
    for(size_t i = 0; i < mThreads.size();i++)
    {
        pthread_join(mThreads[i], NULL);
    }
    return true;
}
bool ThreadPool::addTask(Task* pTask, bool start)
{

    mTasks.push_back(pTask);
    if(start)
    {
        mRunning = true;
        pthread_cond_signal(&mConditionSignal);
    }
    return true;
    //wake up a single thread to deal with a single task (first come, first served)
}

void ThreadPool::addCompleteTask(Task* pTask)
{
    mCompletedTasks.push_back(pTask);
}

Task* ThreadPool::getNextCompletedTask()
{
    Task* t = mCompletedTasks.front();
    mCompletedTasks.pop_front();
    return t;
}


Task* ThreadPool::getNextScheduledTask()
{
    Task* t = mTasks.front();
    mTasks.pop_front();
    return t;
}
bool ThreadPool::isRunning()
{
    return (mRunning);
}
ThreadPool::~ThreadPool()
{
    if(!mShuttingDown)
        shutDownClean();
    mThreads.clear();
    mTasks.clear();
    mCompletedTasks.clear();
}

void* ThreadPool::ThreadFunc(void* ptr)
{
    ThreadPool *pool = (ThreadPool*)ptr;
    Task *task;
    //infinite do nothing loop. The thread will spin it's wheels while it waits for work.
    while(true)
    {

       pthread_mutex_lock(&pool->getMutex());
       while(pool->isRunning() && !pool->hasCurrentTasks())
       {
        //wait on signal from pool to begin
        pthread_cond_wait(&pool->getCondition(), &pool->getMutex());
       }

       //If the pool has tasks needing executed
       if(pool->hasCurrentTasks())
       {
           //get the task and execute it, after unlocking the mutex
           task = pool->getNextScheduledTask();
           pthread_mutex_unlock(&pool->getMutex());
           task->execute();
           //if the task has return data, then add it to the list of completed tasks, for the main thread to evaluate
           if(task->hasReturnData())
           {
               pthread_mutex_lock(&pool->getMutex());
               pool->addCompleteTask(task);
               pthread_mutex_unlock(&pool->getMutex());
           }
           //if not, we need not keep the task object any more
            else
                delete task;
        }
        else
        {
            //stop the pool running, and unlock the mutex
            pool->stop();
            pthread_mutex_unlock(&pool->getMutex());
        }
        if(pool->isShuttingDown())
        {
            break;
        }
    }
    pthread_exit(NULL);
}

以下是main.cpp的代码:

int main(int argc, char** argv)
{
    int numCores = sysconf(_SC_NPROCESSORS_ONLN);

    ThreadPool* pool = new ThreadPool(numCores);    

    for (int i = 0; i < numCores; i++)
    {
        if(!pool->addTask(new TestTask(i)))
            pool->shutDown();
    }
    pool->start();

    if(!pool->shutDownClean())
        return 1;

    else
        return 0;
}

0 个答案:

没有答案