Concurrent use of C ++ STL interface to complete the thread pool

  The last two days saw the concurrency model the following "The C ++ Standard library" in the article. Today, engage in one afternoon, the investigation of the bug, and finally get:

  The interface in general, is to provide concise than pthread.

  Defined task

class task
{
public:
    virtual void execute()=0;
};

  threadpool.h

#ifndef MATHREADPOOL_H
#define MATHREADPOOL_H
#include <queue>
#include "common.h"
#include <vector>
#include <condition_variable>
#include <mutex>
#include <future>
#include <memory>

namespace manch1n
{
using taskSPtr = std::shared_ptr<manch1n::task>;
class mathreadpool : uncopyable
{
public:
    using lockGuard = std::lock_guard<std::mutex>;
    using uniqueLock = std::unique_lock<std::mutex>;

    explicit mathreadpool(size_t nthreads = 4);
    void initAndRun();
    void pushTask(taskSPtr &);
    bool isEmpty();

private:
    static void *routine(void *arg);

    taskSPtr popTask();
    std::vector<std::thread::id> _threads;
    std::queue<taskSPtr> _tasks;
    size_t _nthreads;
    std::mutex _mutex;
    std::condition_variable _condition;
};

} // namespace manch1n

#endif //MATHREADPOOL_H

  threadpool.cc

#include "mathreadpool.h"

namespace manch1n
{
mathreadpool::mathreadpool(size_t nthreads) : _nthreads(nthreads)
{
}

void mathreadpool::initAndRun()
{
    for (int i = 0; i < _nthreads; ++i)
    {
        std::thread t(routine, this);
        t.detach();
        _threads.push_back(t.get_id());
    }
}

void *mathreadpool::routine(void *arg)
{
    mathreadpool &pool = *static_cast<mathreadpool *>(arg);
    while (1)
    {
        taskSPtr ptask = pool.popTask();
        ptask->execute();
    }
    return NULL;
}

void mathreadpool::pushTask(taskSPtr &t)
{
    {
        lockGuard lock(_mutex);
        _tasks.push(t);
    }
    _condition.notify_one();
}

taskSPtr mathreadpool::popTask()
{
    uniqueLock lock(_mutex);
    _condition.wait(lock,[this](){return !this->isEmpty();});
    taskSPtr p(_tasks.front());
    _tasks.pop();
    return p;
}

bool mathreadpool::isEmpty()
{
    return _tasks.empty();
}

} // namespace manch1n

  have a test:

  

#include <iostream>
#include <iomanip>
#include <unistd.h>
#include "mathreadpool.h"
using namespace std;
using namespace manch1n;

class drive1:public manch1n::task
{
public:
    virtual void execute() override
    {
        cout<<s<<endl;
    }
    string s="drive1";
};

class drive2:public manch1n::task
{
public:
    virtual void execute() override
    {
        cout<<s<<endl;
    }
    string s="drive2";
};

int main(int argc, char **argv)
{
    taskSPtr d1=make_shared<drive1>();
    taskSPtr d2=make_shared<drive2>();
    mathreadpool pool(4);
    pool.initAndRun();
    pool.pushTask(d1);
    pool.pushTask(d2);
    ::pause();
    return 0;
}

  Output:

[manch1n@centos7 build]$ ./benchmark 
drive2
drive1
^C
[manch1n@centos7 build]$ ./benchmark 
drive1
drive2
^C
[manch1n@centos7 build]$ ./benchmark 
drive1
drive2

 

Guess you like

Origin www.cnblogs.com/manch1n/p/11773136.html