linux通用線程池設計I

Linux上開發時爲了提高程序的運行效率,經常需要使用的多線程,但是在Linux並沒有看到一套發行的線程池,至少筆者沒有看到。有人會說,用boost就搞定了呀。筆者沒有看過boost源碼,但是感覺過於龐大了,綜上,設計自己使用的線程池還是有實際意義和必要的。

posix線程常用api

pthread_create
pthread_join
pthread_detach
pthread_kill
pthread_cancle
….

線程池設計

線程池需要維護一個任務隊列m_tsk,可以給tsk設計priority,線程優先從任務隊列中取得優先級高的任務。
用戶自定義任務的執行的函數指針,這樣,線程池就可以適用於多種不同的任務了。

源代碼

ThreadMng.h

#ifndef THREADMNG_H_
#define THREADMNG_H_
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pthread.h>
#include <semaphore.h>
#include <vector>
#include <stdio.h>
#include <stdarg.h>
typedef std::vector<void*> TaskContainer;
namespace std_thread_pool
{
    #define echo(format , ...) \
        fprintf(stdout ,"[%s,%s,%d]"format"\n" ,__FILE__,__func__,__LINE__, ##__VA_ARGS__) ;\
        fflush(stdout) ; 
    enum
    {
        e_thread_init = 0 ,
        e_thread_suspend,
        e_thread_working ,
        e_thread_idle 
    };
    typedef struct __thread_info__
    {
        pthread_t id ; 
        int index; 
        int status ;
        void* pthis ; 
    }__attribute__((packed)) thread_info ,*p_thread_info;
    typedef struct __thread_param__
    {
        int (*action)( void*) ; 
        void* param ; 
        int id ; 
        int priority ; 
    }__attribute__((packed)) thread_param ,*p_thread_param;
    class Lock
    {
        public:
        Lock() ; 
        ~Lock() ; 
        public:
        static pthread_mutex_t mutex ; 
    };
    class threadpool
    {
        public:
        threadpool() ;
        ~threadpool() ; 
        public:
        const long start() ; 
        const long end() ; 
        static void *ThreadMain( void *p) ;
        void put(void *p) ; 
        int get( void **p) ;
        void reset() ; 
        private:
        static bool bEnd ; 
        sem_t m_sem_job_wait;
        TaskContainer m_tsk ; 
        p_thread_info m_pThreadInfo ; 
    } ; 

} ;
#endif

ThreadMng.cpp

#include "ThreadMng.h"
#include <sys/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include <signal.h>
using namespace std_thread_pool ; 
pthread_mutex_t Lock::mutex = PTHREAD_MUTEX_INITIALIZER ; 
Lock::Lock()
{
    pthread_mutex_lock( &mutex) ;
}
Lock::~Lock()
{
    pthread_mutex_unlock( &mutex ) ; 
}
bool threadpool::bEnd = false; 
threadpool::threadpool()
{
    sem_init( &m_sem_job_wait , 0 , 0 ) ; 
    m_tsk.clear() ; 
    m_pThreadInfo = new thread_info[4] ; 
}
threadpool::~threadpool()
{
    sem_destroy( &m_sem_job_wait) ; 
    delete [] m_pThreadInfo ; 
}

const long threadpool::start()
{
    for( int i = 0 ; i < 4 ; i++)
    {
        m_pThreadInfo[i].index = i ; 
        m_pThreadInfo[i].status=e_thread_init ; 
        m_pThreadInfo[i].pthis = this ;
        pthread_create(&m_pThreadInfo[i].id , NULL , threadpool::ThreadMain ,\
        (void*)&m_pThreadInfo[i] ) ; 
    }
    return 0 ; 
}

const long threadpool::end() 
{
    {
        Lock oLock ; 
        bEnd = true ; 
    }
    for( int i = 0 ; i < 4 ; i++)
    {
        if( pthread_kill( m_pThreadInfo[i].id , 0 ) == 0 )
        {
            pthread_join(m_pThreadInfo[i].id , NULL ); 
        }
    }
    return 0; 
}

void *threadpool::ThreadMain( void *p)
{
    if( !p )
    {
        pthread_exit( 0 ) ; 
    }
    p_thread_info pthread = (p_thread_info) p ; 
    pthread->status = e_thread_suspend ; 
    void *tsk =NULL;
    threadpool *pthis = (threadpool*)pthread->pthis ; 
    while( !bEnd && !pthis->get( &tsk) )
    {
        pthread->status = e_thread_working ; 
        p_thread_param pParam  = (p_thread_param)tsk ; 
        (*pParam->action)(pParam->param) ;
        pthread->status = e_thread_idle ; 
    }
    return NULL; 
}

void threadpool::put(void *p)
{

    {
        Lock oLock ; 
        m_tsk.push_back( p ) ;
    }
    sem_post(&m_sem_job_wait) ; 
}

int threadpool::get(void **p) 
{
    sem_wait(&m_sem_job_wait) ; 
    {
        Lock oLock ; 
        if(m_tsk.size()  )
        {
            TaskContainer::iterator it_tsk = m_tsk.begin() ; 
            *p = *it_tsk ; 
            m_tsk.erase( it_tsk ) ; 
        }
        return 0;
    }
    return -1; 
}

MakeFile

CC := g++
CFLAGS := -g -Wall
TARGET := libthreadpool.so
SRCS := $(wildcard *.cpp)
OBJS := $(patsubst %cpp,%o,$(SRCS))
LIB=-lpthread
INCLUDE=-I./
all:$(TARGET)
$(OBJS):$(SRCS)
    $(CC) -c $< -g $(LIB) $(INCLUDE)
$(TARGET):$(OBJS)
    #ar -rc $@ $^
    $(CC) -shared -fPIC -o $@ $^
clean:
    rm -rf $(TARGET) *.o

線程池啓動之後,處於hangup狀態,任務來到時線程纔會轉入到working狀態。
多線程編程時,內存的持久化是一個永恆的命題。用戶自定義的thread_param對象必須是持久化得對象.(new alloc malloc)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章