07C++11线程池2

1. 线程池DLL工程

​ defs.h中定义了导入导出符、单元测试相关宏、错误码等。

//defs.h
#ifndef __ROCK_THREAD_POOL_DEFS_H__
#define __ROCK_THREAD_POOL_DEFS_H__

#if defined WIN32 || defined WIN64
    #ifdef  THREAD_POOL_DLL_BUILD
        #define  THREAD_POOL_API _declspec(dllexport)
#elif defined( THREAD_POOL_DLL_USE )
#define  THREAD_POOL_API _declspec(dllimport)
    #else
#define  THREAD_POOL_API
    #endif
#else // WIN32
#define  THREAD_POOL_API
#endif // WIN32

/// UNIT TEST MACRO
#ifdef  __UT_TEST__
#define PUBLIC       public
#define PRIVATE      public
#define PROTECTED    public
#else
#define PUBLIC       public
#define PRIVATE      private
#define PROTECTED    protected
#endif //  UT_TEST


#include <memory>
#include <vector>
#include <list>
#include <thread>
#include <functional>
#include <atomic>

#define ROCK_OS_TOOLS_NAMESPACE_BEGIN namespace rock { namespace os_tools {
#define ROCK_OS_TOOLS_NAMESPACE_END } }

ROCK_OS_TOOLS_NAMESPACE_BEGIN

// 错误码
enum ThreadPoolError
{
	THREAD_POOL_ERROR_NO = 0,
    THREAD_POOL_ERROR_GENERAL = -1
};

ROCK_OS_TOOLS_NAMESPACE_END

#endif // end of ROCK_OS_TOOLS_NAMESPACE_END

​ 线程池接口头文件

//thread_pool.h
#ifndef __ROCK_THREAD_POOL_H__
#define __ROCK_THREAD_POOL_H__
#include "defs.h"

ROCK_OS_TOOLS_NAMESPACE_BEGIN

class THREAD_POOL_API ThreadPool
{
PUBLIC:
    const int MAX_TASK_COUNT = 100;
    using Task = std::function<void()>;

PUBLIC:

    static ThreadPool& instance();

    virtual void start(const int& threadCount = std::thread::hardware_concurrency()) = 0;

    virtual void stop() = 0;

    virtual void addTask(Task&& task) = 0;

    virtual void addTask(const Task& task) = 0;

};
typedef std::shared_ptr<ThreadPool> ThreadPoolSPtr;

ROCK_OS_TOOLS_NAMESPACE_END
#endif //__ROCK_THREAD_POOL_H__


​ 线程池接口cpp文件

//thread_pool.cpp
#include "thread_pool_imp.h"

rock::os_tools::ThreadPool& rock::os_tools::ThreadPool::instance()
{
    static ThreadPoolImp inst;
    return inst;
}


线程池实现头文件

//thread_pool_imp.h
#ifndef __ROCK_THREAD_POOL_IMP_H__
#define __ROCK_THREAD_POOL_IMP_H__

#include "thread_pool.h"
#include "sync_queue.h"

ROCK_OS_TOOLS_NAMESPACE_BEGIN

class ThreadPoolImp : public ThreadPool
{
PUBLIC:

    ThreadPoolImp();

    ~ThreadPoolImp();

    virtual void start(const int& threadCount = std::thread::hardware_concurrency()) override;

    virtual void stop() override;

    virtual void addTask(Task&& task) override;

    virtual void addTask(const Task& task) override;

PRIVATE:

    void startThreadGroup(const int& threadCount);

    void runInThread();

    void stopThreadGroup();

    std::list<std::shared_ptr<std::thread>> m_threadGroup;
    SyncQueue<Task> m_queue;
    atomic_bool m_running;
    std::once_flag m_flag;
};

ROCK_OS_TOOLS_NAMESPACE_END

#endif //__ROCK_THREAD_POOL_IMP_H__

​ 线程池实现cpp

//thread_pool_imp.cpp
#include "thread_pool_imp.h"


rock::os_tools::ThreadPoolImp::ThreadPoolImp() 
    :m_queue(MAX_TASK_COUNT)
{
    m_running = false;
}

rock::os_tools::ThreadPoolImp::~ThreadPoolImp()
{
    stop();
}

void rock::os_tools::ThreadPoolImp::start(const int& threadCount /*= std::thread::hardware_concurrency()*/)
{
    if (!m_running)
    {
        startThreadGroup(threadCount);
    }
}


void rock::os_tools::ThreadPoolImp::stop()
{
    //std::call_once(m_flag, [this](){stopThreadGroup(); });
    if (m_running)
    {
        stopThreadGroup();
    }
}

void rock::os_tools::ThreadPoolImp::addTask(Task&& task)
{
    m_queue.put(std::forward<Task>(task));
}

void rock::os_tools::ThreadPoolImp::addTask(const Task& task)
{
    m_queue.put(task);
}


void rock::os_tools::ThreadPoolImp::startThreadGroup(const int& threadCount)
{
    m_queue.start();
    m_running = true;

    for (int i = 0; i < threadCount; ++i)
    {
        m_threadGroup.push_back(std::make_shared<std::thread>(&ThreadPoolImp::runInThread, this));
    }

}

void rock::os_tools::ThreadPoolImp::runInThread()
{
    while (m_running)
    {
        Task task;
        m_queue.take(task);
        if (!m_running)
        {
            return;
        }
        if (task)
        {
            task();
        }
    }
}

void rock::os_tools::ThreadPoolImp::stopThreadGroup()
{
    m_queue.stop();
    m_running = false;

    for (auto& thread : m_threadGroup)
    {
        if (thread)
        {
            thread->join();
        }
    }
    m_threadGroup.clear();
}

​ gtest单元测试main文件

//ut_main.cpp

#include "gtest/gtest.h"
#include "gmock/gmock.h"

int main(int argc, char **argv)
{
	testing::InitGoogleTest(&argc, argv);
	testing::InitGoogleMock(&argc, argv);
	return RUN_ALL_TESTS();
}


​ gtest单元测试文件

//ut_thread_pool.cpp

#include "gtest/gtest.h"

#include "thread_pool.h"

using namespace rock::os_tools;
using namespace std;

class ThreadPoolTest : public testing::Test
{
public:
    ThreadPoolTest():m_pool(ThreadPool::instance())
    {
        
    }
    ~ThreadPoolTest()
    {
        m_pool.stop();
    }

    virtual void SetUp()
    {

    }

    virtual void TearDown()
    {
        m_pool.stop();
    }

protected:

    ThreadPool& m_pool;
};

TEST_F(ThreadPoolTest, 001_instance_1)
{
    m_pool.start(1);

    for (int i = 0; i < 10; ++i)
    {
        //因为这个地方可以使用lamda表达式捕获参数,所以Task定义成无参类型是合理的。
        m_pool.addTask([i]{
            cout << "doing tast:" << i << " in thread " << this_thread::get_id() << endl;
            this_thread::sleep_for(std::chrono::seconds(1));
        });
    }

    this_thread::sleep_for(std::chrono::seconds(11));
}

TEST_F(ThreadPoolTest, 001_instance_2)
{
    m_pool.start(2);

    for (int i = 0; i < 10; ++i)
    {
        //因为这个地方可以使用lamda表达式捕获参数,所以Task定义成无参类型是合理的。
        m_pool.addTask([i]{
            cout << "doing tast:" << i << " in thread " << this_thread::get_id() << endl;
            this_thread::sleep_for(std::chrono::seconds(1));
        });
    }
    this_thread::sleep_for(std::chrono::seconds(6));
}

TEST_F(ThreadPoolTest, 001_instance_4)
{
    m_pool.start(4);

    for (int i = 0; i < 10; ++i)
    {
        //因为这个地方可以使用lamda表达式捕获参数,所以Task定义成无参类型是合理的。
        m_pool.addTask([i]{
            cout << "doing tast:" << i << " in thread " << this_thread::get_id() << endl;
            this_thread::sleep_for(std::chrono::seconds(1));
        });
    }
    this_thread::sleep_for(std::chrono::seconds(6));
}

TEST_F(ThreadPoolTest, 001_instance_5)
{
    m_pool.start(4);

    for (int i = 0; i < 20; ++i)
    {
        //因为这个地方可以使用lamda表达式捕获参数,所以Task定义成无参类型是合理的。
        m_pool.addTask([i]{
            cout << "doing tast:" << i << " in thread " << this_thread::get_id() << endl;
            this_thread::sleep_for(std::chrono::seconds(1));
        });
    }
    this_thread::sleep_for(std::chrono::seconds(6));
}

image

posted @ 2020-06-19 16:17  洛克十年  阅读(157)  评论(0编辑  收藏  举报