zoukankan      html  css  js  c++  java
  • pthread库实现一个简单的任务池

    pthread库实现一个简单的任务池
    类关系图:

    说明:
            1:TaskManager类管理Task类,Task类是一个纯虚类;
            2:ThreadManager类管理Thread类,Thread类封装pthread库的相关线程函数;
            3:Thread类通过TaskManager类获取需要执行的任务;
            4:ThreadManager类中包含一个TaskManager用于管理需要其管理线程执行的Task;
            5:UserTask是用户继承Task类而来的用户自己的任务类,最后线程池中运行的任务就是UserTask。

    该交代的都交代了,现在上代码。^-^

    Task.h
    /**********************
    * author: zhanghang
    * date: 2016.02.27
    * file: Task.h
    * usage: this is the pure virtual base class of the task in the task pool
    ***********************/
    
    #ifndef _TASK_H
    #define _TASK_H
    
    #define TIMES_OF_SLEEP_ONE_SEC 1500000
    
    class Task
    {
    public:
        Task(){};
        virtual ~Task(){};
        virtual void Process() = 0;
        // all the delay operations should use this function
        void Delay(int sec)
        {   
            for(int i=0; i<sec; ++i)
            {
                for(int j=0; j<TIMES_OF_SLEEP_ONE_SEC; ++j)
                {
                }
            }
        }   
    };
    
    #endif
    

    自己封装了一个锁类,GuardLock.h
    /************************
    * author: zhanghang
    * date: 2016.02.27
    * file: GuardLock.h
    * usage: this class to lock a code scope
    ************************/
    
    #ifndef _GUARD_LOCK_H
    #define _GUARD_LOCK_H
    
    #include <pthread.h>
    #include <iostream>
    
    class GuardLock
    {
    public:
        GuardLock(pthread_mutex_t *pMutex):m_pMutex(pMutex)
        {
            pthread_mutex_lock(m_pMutex);
        }
        ~GuardLock()
        {   
            pthread_mutex_unlock(m_pMutex);
        }
    private:
        pthread_mutex_t *m_pMutex;
    };      
        
    #endif
    

    TaskManager.h
    /************************
    * author: zhanghang
    * date: 2016.02.27
    * file: TaskManager.h
    * usage: this class is to manage the tasks
    ***********************/
    
    #ifndef _TASK_MANAGER_H
    #define _TASK_MANAGER_H
    
    #include <pthread.h>
    #include <list>
    class Task;
    
    class TaskManager
    {
    public:
        TaskManager();
        ~TaskManager();
        void AddTask(Task *pTask);
        void DeleteAllTask();
        int GetTaskNum();
        Task *GetATask();
    private:
        std::list<Task *> m_TaskList;
        pthread_mutex_t m_AccTaskListMutex;
    };      
        
    #endif
    

    TaskManager.cpp
    /************************
    * author: zhanghang
    * date: 2016.02.27
    * file: TaskManager.cpp
    * usage: this class is to manage the tasks
    ***********************/
    
    #include "GuardLock.h"
    #include "TaskManager.h"
    #include "Task.h"
    #include <iostream>
    
    TaskManager::TaskManager()
    {
        std::cout << "TaskManager::TaskManager*" << (void *)this << std::endl;
    }
    
    TaskManager::~TaskManager()
    {   
        std::cout << "TaskManager::~TaskManager#" << (void *)this << std::endl;
        
        if(m_TaskList.size() > 0)
        {
            DeleteAllTask();
        }
    }   
    
    void TaskManager::AddTask(Task *pTask)
    {
        GuardLock lock(&m_AccTaskListMutex);
    
        if(NULL != pTask)
        {
            m_TaskList.push_back(pTask);
        }
    }
    
    void TaskManager::DeleteAllTask()
    {
        GuardLock lock(&m_AccTaskListMutex);
    
        std::list<Task *>::iterator taskItr = m_TaskList.begin();
        while(m_TaskList.end() != taskItr)
        {
            delete *taskItr;
            ++taskItr;
        }
        m_TaskList.clear();
    }
    
    int TaskManager::GetTaskNum()
    {
        return m_TaskList.size();
    }
    
    Task *TaskManager::GetATask()
    {
        GuardLock lock(&m_AccTaskListMutex);
    
        Task *pTask = NULL;
        std::list<Task *>::iterator taskBeg = m_TaskList.begin();
        if(m_TaskList.end() != taskBeg)
        {
            pTask = (*taskBeg);
            m_TaskList.erase(taskBeg);
        }
        return pTask;
    }
           

    Thread.h
    /************************
    * author: zhanghang
    * date: 2016.02.27
    * file: Thread.h
    * usage: this class is to new a thread
    ***********************/
            
    #ifndef _THREAD_H
    #define _THREAD_H
    
    #include <pthread.h>
    
    #define TIMES_OF_SLEEP_ONE_SEC 1500000
    
    class Task;
    class TaskManager;
    
    // the entrance of the new thread
    void *ThreadMain(void *pArg);
    
    class Thread
    {
    public:
        Thread(TaskManager &taskManager);
        ~Thread();
        int Run();
        int Stop();
        bool IsFree();
        // because there is one cnacel point in the sleep func
        // so i write my own delay func
        void Delay(int sec);
    
        friend void *ThreadMain(void *pArg);
    private:
        bool m_IsFree;
        bool m_ExitFlag;
        Task *m_pTask;
        TaskManager &m_TaskMgr;
        pthread_t m_ThreadID;
    };
    
    #endif
    

    Thread.cpp
    /************************
    * author: zhanghang
    * date: 2016.02.27
    * file: Thread.cpp
    * usage: this class is to new a thread
    ***********************/
    
    #include "Thread.h"
    #include "Task.h"
    #include "TaskManager.h"
    #include <iostream>
    
    Thread::Thread(TaskManager &taskMgr)
    : m_IsFree(true), m_ExitFlag(false), m_pTask(NULL), m_TaskMgr(taskMgr), m_ThreadID(0)
    {
        std::cout << "Thread::Thread*" << (void *)this << std::endl;
    }
    
    Thread::~Thread()
    {
        std::cout << "Thread::~Thread#" << (void *)this << std::endl;
    
        if(!m_ExitFlag)
        {
            m_ExitFlag = true;
        }
    }   
        
    int Thread::Run()
    {   
        return pthread_create(&m_ThreadID, NULL, ThreadMain, this);
    }
    
    int Thread::Stop()
    {
        m_ExitFlag = true;
        void *pRet = NULL;
        pthread_cancel(m_ThreadID);
        return pthread_join(m_ThreadID, &pRet);
    }
    
    bool Thread::IsFree()
    {
        return m_IsFree;
    }
    
    void Thread::Delay(int sec)
    {
        for(int i=0; i<sec; ++i)
        {
            for(int j=0; j<TIMES_OF_SLEEP_ONE_SEC; ++j)
            {
            }
        }
    }
    
    // thre entrance of thread
    void *ThreadMain(void *pArg)
    {
        if(NULL == pArg)
        {
            return NULL;
        }
    
        // set the cancel state to enable
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
        // set the cancel type to run to next cnacel point
        pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
    
        Thread &rThread = *((Thread *)pArg);
    
        while(!rThread.m_ExitFlag)
        {
            rThread.m_pTask = rThread.m_TaskMgr.GetATask();
    
            // there is no task
            if(NULL == rThread.m_pTask)
            {
                rThread.m_IsFree = true;
                //sleep(1); // do not use sleep function, there is some cancel point in the function
                rThread.Delay(1);
                continue;
            }
    
            rThread.m_IsFree = false;
            // the mission
            rThread.m_pTask->Process();
    
            // clear the task room
            delete rThread.m_pTask;
            rThread.m_pTask = NULL;
    
            // set a cancel point
            pthread_testcancel();
        }
    }
                           

    ThreadManager.h
    /************************
    * author: zhanghang
    * date: 2016.02.07
    * file: ThreadManager.h
    * usage: this class is to manage the threads
    *******************************/
    
    #ifndef _THREAD_MANAGER_H
    #define _THREAD_MANAGER_H
    
    #include <list>
    class Task;
    class Thread;
    class TaskManager;
    
    class ThreadManager
    {
    public:
        ThreadManager();
        ~ThreadManager();
        int StartThreads(int num);
        int StopThreads();
        void AddTask(Task *);
        int GetTaskNum();
        int GetThreadNum();
        bool CreateTaskManager();
    private:
        std::list<Thread *> m_ThreadList;
        TaskManager *m_pTaskMgr;
    };
    
    #endif
    

    ThreadManager.cpp
    /*********************
    * author: zhanghang
    * date: 2016.02.27
    * file: ThreadManager.cpp
    * usage: this class is to manage the task pool
    *************************/
    
    #include <iostream>
    #include "ThreadManager.h"
    #include "Thread.h"
    #include "Task.h"
    #include "TaskManager.h"
    
    ThreadManager::ThreadManager(): m_pTaskMgr(NULL)
    {
        std::cout << "ThreadManager::ThreadManager*" << (void *)this << std::endl;
    }
    
    ThreadManager::~ThreadManager()
    {
        std::cout << "ThreadManager::~ThreadManager#" << (void *)this << std::endl;
        if(m_ThreadList.size() > 0)
        {   
            StopThreads();
        }   
    
        if(NULL != m_pTaskMgr)
        {   
            delete m_pTaskMgr;
            m_pTaskMgr = NULL;
        }   
    }
    
    bool ThreadManager::CreateTaskManager()
    {
        if(NULL == m_pTaskMgr)
        {   
            m_pTaskMgr = new TaskManager();
            if(NULL == m_pTaskMgr)
            {
                return false;
            }
        }
        return true;
    }
    
    // return the truely thread num
    int ThreadManager::StartThreads(int num)
    {
        if(!CreateTaskManager())
        {
            return 0;
        }
    
        int result = 0;
        for(int i=0; i<num; ++i)
        {
            Thread *pThread = NULL;
            pThread = new Thread(*m_pTaskMgr);
    
            result = pThread->Run();
            if(0 != result)
            {
                std::cout << "one thread started failed! error code: " << result << std::endl;
                continue;
            }
    
            m_ThreadList.push_back(pThread);
        }
    
        return m_ThreadList.size();
    }
    
    // return the num of threads that left
    int ThreadManager::StopThreads()
    {
        std::list<Thread *>::iterator threadItr = m_ThreadList.begin();
        int result = 0;
        while(m_ThreadList.end() != threadItr)
        {
            result = (*threadItr)->Stop();
    
            if(0 != result)
            {
                std::cout << "one thread stopped failed! error code: " << result << std::endl;
                ++threadItr;
                continue;
            }
    
            // delete the thread
            delete *threadItr;
            m_ThreadList.erase(threadItr++);
        }
    
        // the left thread
        return m_ThreadList.size();
    }
    
    void ThreadManager::AddTask(Task *pTask)
    {
        if(!CreateTaskManager())
        {
            return;
        }
    
        m_pTaskMgr->AddTask(pTask);
    }
    
    int ThreadManager::GetTaskNum()
    {
        if(!CreateTaskManager())
        {
            return 0;
        }
    
        return m_pTaskMgr->GetTaskNum();
    }
    
    int ThreadManager::GetThreadNum()
    {
        return m_ThreadList.size();
    }
              

    main.cpp
    /*************
    * author: zhanghang
    * date: 2016.02.27
    * file: main.cpp
    * usage: this is a demo of taskpool
    ********************************/
    
    #include "ThreadManager.h"
    #include "Task.h"
    #include <iostream>
    #include <unistd.h>
    
    
    #define THREAD_NUM 3
    
    // this is the task
    class MyTask : public Task
    {
    public:
        MyTask()
        {
            std::cout << "MyTask::MyTask*" << (void *)this << std::endl;
        }
        ~MyTask()
        {
            std::cout << "MyTask::~MyTask#" << (void *)this << std::endl;
        }
        void Process()
        {
            std::cout << "thread id: " << pthread_self() << std::endl;
            Delay(1);
        }
    };
    
    int main(int argc, char **argv)
    {
        ThreadManager threadMgr;
        threadMgr.StartThreads(THREAD_NUM);
    
        for(int i=0; i<20; ++i)
        {
            MyTask *pMyTask = new MyTask();
            Task *pTask = (Task *) pMyTask;
    
            // add task
            threadMgr.AddTask(pTask);
        }
    
        sleep(4);
    
        threadMgr.StopThreads();
    
        return 1;
    }
             

    makefile
    main: ThreadMgr Thread TaskMgr
        g++ -o main main.cpp ThreadManager.o Thread.o TaskManager.o -lpthread -g
    ThreadMgr:
        g++ -c ThreadManager.cpp ThreadManager.h Thread.h TaskManager.h Task.h -g
    Thread:
        g++ -c Thread.cpp Thread.h Task.h TaskManager.h -g
    TaskMgr:
        g++ -c TaskManager.cpp TaskManager.h GuardLock.h Task.h -g
    
    clean:
        rm *.o
    

    运行程序后程序的输出:

    ThreadManager::ThreadManager*0xbfdf52d4
    TaskManager::TaskManager*0x8599008
    Thread::Thread*0x8599030
    Thread::Thread*0x85990f0
    Thread::Thread*0x85991b0
    MyTask::MyTask*0x8599270
    MyTask::MyTask*0x8599290
    MyTask::MyTask*0x85992b0
    MyTask::MyTask*0x85992d0
    MyTask::MyTask*0x85992f0
    MyTask::MyTask*0x8599310
    MyTask::MyTask*0x8599330
    MyTask::MyTask*0x8599350
    MyTask::MyTask*0x8599370
    MyTask::MyTask*0x8599390
    MyTask::MyTask*0x85993b0
    MyTask::MyTask*0x85993d0
    MyTask::MyTask*0x85993f0
    MyTask::MyTask*0x8599410
    MyTask::MyTask*0x8599430
    MyTask::MyTask*0x8599450
    MyTask::MyTask*0x8599470
    MyTask::MyTask*0x8599490
    MyTask::MyTask*0x85994b0
    MyTask::MyTask*0x85994d0
    thread id: 3058080576
    thread id: 3074865984
    thread id: 3066473280
    MyTask::~MyTask#0x8599270
    thread id: 3058080576
    MyTask::~MyTask#0x8599290
    thread id: 3074865984
    MyTask::~MyTask#0x85992b0
    thread id: 3066473280
    MyTask::~MyTask#0x85992d0
    thread id: 3058080576
    MyTask::~MyTask#0x85992f0
    thread id: 3074865984
    MyTask::~MyTask#0x8599310
    thread id: 3066473280
    MyTask::~MyTask#0x8599330
    thread id: 3058080576
    MyTask::~MyTask#0x8599350
    thread id: 3074865984
    MyTask::~MyTask#0x8599370
    thread id: 3066473280
    MyTask::~MyTask#0x85993b0
    thread id: 3074865984
    MyTask::~MyTask#0x8599390
    thread id: 3058080576
    MyTask::~MyTask#0x85993f0
    thread id: 3074865984
    MyTask::~MyTask#0x85993d0
    thread id: 3066473280
    MyTask::~MyTask#0x8599410
    thread id: 3058080576
    MyTask::~MyTask#0x8599430
    thread id: 3074865984
    MyTask::~MyTask#0x8599450
    thread id: 3066473280
    MyTask::~MyTask#0x8599470
    thread id: 3058080576
    MyTask::~MyTask#0x8599490
    MyTask::~MyTask#0x85994b0
    MyTask::~MyTask#0x85994d0
    Thread::~Thread#0x8599030
    Thread::~Thread#0x85990f0
    Thread::~Thread#0x85991b0
    ThreadManager::~ThreadManager#0xbfdf52d4
    TaskManager::~TaskManager#0x8599008


    谢谢。
  • 相关阅读:
    罗素语录
    《一步一步写嵌入式操作系统》读书笔记1—Skyeye介绍、安装和HelloWorld
    在Raspberry Pi上安装XBMC
    Raspberry Pi上手
    axios案例
    php+mysql修改数据库数据
    将前台输入的“意见反馈”提交到后台数据库
    用JavaScript动态生成HTML(PHP+MYSQL)(2)
    用JavaScript动态生成HTML(PHP+MYSQL)(1)
    SQL课堂笔记--设计数据库
  • 原文地址:https://www.cnblogs.com/zhanghang-BadCoder/p/6476456.html
Copyright © 2011-2022 走看看