简单的线程池c/c++

linux 下的C语言版本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>

#define LL_INSERT(item,list) do{\
    item->prev = NULL;\
    item->next = list;\
    if(list!=NULL) list->prev=item;\
    list = item;\
}while(0)

#define LL_REMOVE(item,list) do {\
    if(item->prev !=NULL) item->prev->next = item->next;\
    if(item->next !=NULL) item->next->prev = item->prev;\
    if(list == item) list = item->next;\
    item->prev = item->next=NULL;\
}while(0)
//任务结构体
//具体的任务处理函数 用户传进来的参数(在必要的时候传给处理函数) 
//因为任务需要放在队列里面,而且这个队列要很方便地插入和删除,所以使用链表比较好
struct NJOB {
    void (*func)(void* args);
    void *user_data;
    struct NJOB* prev;
    struct NJOB* next;
};
//执行任务的线程需要有一些属性辅助工作,所以封装一个worker结构体,存放辅助变量
//线程,线程退出标志 ,线程闲置标志,所属线程池的句柄
//同理这些线程要放在一个地方以便使用,考虑到可能动态的增加线程或者减少线程,所以
//也用一个链表存放
struct MANAGER;
struct NWORKER {
    pthread_t th;
    int terminate;
    int idle;
    struct MANAGER* pool;

    struct NWORKER* prev;
    struct NWORKER* next;
};

//线程队列和任务队列之间的调度,需要控制,所以加一个manager
//任务队列会被多个线程共享,是临界资源,需要加锁保护  mtx cond 
struct MANAGER {
    struct NJOB* jobs;
    struct NWORKER* workers;
    int numworkers;
    pthread_mutex_t jobs_mtx;
    pthread_cond_t jobs_cond;
};
typedef struct MANAGER nThreadPool;

static void* nThreadEntranceFunc(void* arg){
    struct NWORKER* wkr = (struct NWORKER*)arg;
    struct MANAGER* pool = wkr->pool;
    while(1){
        pthread_mutex_lock(&pool->jobs_mtx);
        while(pool->jobs==NULL){
            if(wkr->terminate>0)break;
            wkr->idle = 1;
            //等待被条件唤醒,一旦被唤醒就会开始抢锁,只有拿到锁pthread_cond_wait才会返回
            pthread_cond_wait(&pool->jobs_cond,&pool->jobs_mtx);
        }
        if(wkr->terminate>0){
            pthread_mutex_unlock(&pool->jobs_mtx);
            break;
        }
        wkr->idle = 0;
        struct NJOB* job = pool->jobs;
        for(;job->next!=NULL;job=job->next);
        LL_REMOVE(job,pool->jobs);
        pthread_mutex_unlock(&pool->jobs_mtx);
        job->func(job->user_data);
        free(job->user_data);
        free(job);
    }
    free(wkr);
    return NULL;
}

int nThreadPoolInit(nThreadPool *pool, int numworkers){
    if(numworkers<1) numworkers=1;
    if(pool==NULL) return -1;
    memset(pool,0,sizeof(nThreadPool));
    pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;
    memcpy(&pool->jobs_cond,&blank_cond,sizeof(pthread_cond_t));
    pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;
    memcpy(&pool->jobs_mtx,&blank_mutex,sizeof(pthread_mutex_t));

    int i=0;
    for(;i<numworkers;i++){
        struct NWORKER* wkr= (struct NWORKER*)malloc(sizeof(struct NWORKER));
        if(wkr==NULL){
            return -2;
        }
        memset(wkr,0,sizeof(struct NWORKER));
        wkr->pool = pool;
        int ret = pthread_create(&wkr->th,NULL,nThreadEntranceFunc,(void*)wkr);
        if(ret!=0){
            free(wkr);
            return -3;
        }
        LL_INSERT(wkr,pool->workers);
        pool->numworkers += 1;
    }
    return 0;
}

void nThreadPoolJobPush(nThreadPool *pool, struct NJOB* job){
    pthread_mutex_lock(&pool->jobs_mtx);
    LL_INSERT(job,pool->jobs);
    pthread_mutex_unlock(&pool->jobs_mtx);
    //如果cond_wait队列不为空,则至少将一个线程从cond_wait内部的阻塞状态唤醒
    pthread_cond_signal(&pool->jobs_cond);
}

int  nThreadPoolWorkerAdd(nThreadPool *pool,int num){
    if(pool==NULL||pool->workers==NULL)
        return  -1;
    for(int i=0;i<num;i++){
        struct NWORKER* wkr= (struct NWORKER*)malloc(sizeof(struct NWORKER));
        if(wkr==NULL){
            return -2;
        }
        memset(wkr,0,sizeof(struct NWORKER));
        wkr->pool = pool;
        int ret = pthread_create(&wkr->th,NULL,nThreadEntranceFunc,wkr);
        if(ret!=0){
            free(wkr);
            return -3;
        }
        LL_INSERT(wkr,pool->workers);
        pool->numworkers+=1;
    }
    return pool->numworkers;
}

int  nThreadPoolWorkerDrop(nThreadPool *pool,int num){
    struct NWORKER* wkr = pool->workers;
    int count=0;
    pthread_mutex_lock(&pool->jobs_mtx);
    for(;wkr!=NULL;wkr=wkr->next){
        if(wkr->idle>0){
            wkr->terminate=1;
            count++;
        }
        if(count>=num)break;
    }
    pthread_mutex_unlock(&pool->jobs_mtx);
    pthread_cond_broadcast(&pool->jobs_cond);
    return count;
}

void nThreadPoolDestroy(nThreadPool *pool){
    struct NWORKER* wkr=NULL;
    for(wkr=pool->workers;wkr!=NULL;wkr=wkr->next)
        wkr->terminate=1;
    pthread_cond_broadcast(&pool->jobs_cond);
    // make sure pool is terminate indeed.
    sleep(1); 
    return;
}

//以下是模拟客户端程序
struct ArgCallback{
    char name[15];
    int age;
};

void callbacks(void* arg){
    struct ArgCallback* para=(struct ArgCallback*)arg;
    sleep(1);
    printf("name=%s, age=%d\n",para->name,para->age);
}

void EXIT(int sig){
    printf("外部信号:%d,主进程退出\n",sig);
    exit(0);
}

int main(int argc, char* args[]){
    nThreadPool Pool;
    nThreadPoolInit(&Pool,50);
    for(int i=0;i<500;i++){
        struct NJOB* job=(struct NJOB*)malloc(sizeof(struct NJOB));
        memset(job,0,sizeof(struct NJOB));
        struct ArgCallback* arg=(struct ArgCallback*)malloc(sizeof(struct ArgCallback));
        memset(arg,0,sizeof(struct ArgCallback));
        sprintf(arg->name,"id_%d",i);
        arg->age=i;
        job->user_data=(void*)arg;
        job->func=callbacks;
        nThreadPoolJobPush(&Pool,job);
    }
    int isdestroyed=0;
    while(1){
        char c = getchar();
        if(c=='d'){
            nThreadPoolDestroy(&Pool);
            isdestroyed = 1;
        }
        if(isdestroyed!=0&&c=='q')
            break;
    }
    return 0;
    // signal(SIGINT,EXIT); //ctrl+c signal
    // signal(SIGTERM,EXIT);//kill -15 signal
    // while(1){
    //     sleep(10);
    // }
    // return 0;
}

跨平台的c++版本:

#include <thread>
#include <mutex>
#include <condition_variable>
#include <list>
#include <cstring>
#include <iostream>

struct NJOB {
    void (*func)(void* args);
    void *user_data;
};

struct MANAGER;
struct NWORKER {
    std::thread th;
    int terminate;
    int idle;
    struct MANAGER* pool;
};

struct MANAGER {
    std::list<NJOB*>  jobs;
    std::list<NWORKER*> workers;
    int numworkers;
    std::mutex jobs_mtx;
    std::condition_variable jobs_cond;
};
typedef struct MANAGER nThreadPool;

static void* nThreadEntranceFunc(void* arg){
    struct NWORKER* wkr = (struct NWORKER*)arg;
    struct MANAGER* pool = wkr->pool;
    while(1){
        std::unique_lock<std::mutex> lock(pool->jobs_mtx);
        while(pool->jobs.empty()){
            if(wkr->terminate>0)break;
            wkr->idle = 1;
            //[1.解锁 2.当前线程入队cond_wait],wait函数会保证这两步一起执行,不被打断
            //如果该线程从cond_wait中被移出,表明已经被唤醒,会进入抢锁状态,只有拿到锁后才会退出wait
            pool->jobs_cond.wait(lock);
        }
        std::mutex* lPtr = lock.release();
        if(wkr->terminate>0){
            lPtr->unlock();
            break;
        }
        wkr->idle = 0;
        struct NJOB* job = pool->jobs.back();
        pool->jobs.pop_back();
        lPtr->unlock();
        job->func(job->user_data);
        free(job->user_data);
        free(job);
    }
    free(wkr);
    return NULL;
}

int nThreadPoolInit(nThreadPool *pool, int numworkers){
    if(numworkers<1) numworkers=1;
    if(pool==NULL) return -1;
    int i=0;
    for(;i<numworkers;i++){
        struct NWORKER* wkr= (struct NWORKER*)malloc(sizeof(struct NWORKER));
        if(wkr==NULL){
            return -2;
        }
        memset(wkr,0,sizeof(struct NWORKER));
        wkr->pool = pool;
        std::thread* t = new(&(wkr->th)) std::thread(nThreadEntranceFunc,(void*)wkr);
        //t->detach();
        pool->workers.push_front(wkr);
        pool->numworkers += 1;
    }
    return 0;
}

void nThreadPoolJobPush(nThreadPool *pool, struct NJOB* job){
    {
        std::unique_lock<std::mutex> lock(pool->jobs_mtx);
        pool->jobs.push_front(job);
    }
    //如果cond_wait队列不为空,则至少将一个线程从cond_wait内部的阻塞状态唤醒
    pool->jobs_cond.notify_one();
}

void nThreadPoolDestroy(nThreadPool *pool){
    std::list<NWORKER*>::iterator it;
    for(it=pool->workers.begin();it!=pool->workers.end();it++)
        (*it)->terminate=1;
    pool->jobs_cond.notify_all();
    // make sure pool is terminate in real.
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    return;
}

int  nThreadPoolWorkerAdd(nThreadPool *pool,int num){
    if(pool==NULL)
        return  -1;
    for(int i=0;i<num;i++){
        struct NWORKER* wkr= (struct NWORKER*)malloc(sizeof(struct NWORKER));
        if(wkr==NULL){
            return -2;
        }
        memset(wkr,0,sizeof(struct NWORKER));
        wkr->pool = pool;
        std::thread* t = new(&(wkr->th)) std::thread(nThreadEntranceFunc,(void*)wkr);
        //t->detach();
        pool->workers.push_front(wkr);
        pool->numworkers+=1;
    }
    return pool->numworkers;
}

int  nThreadPoolWorkerDrop(nThreadPool *pool,int num){
    int count=0;
    pool->jobs_mtx.lock();
    std::list<NWORKER*>::iterator it;
    for(it=pool->workers.begin();it!=pool->workers.end();it++){
        if((*it)->idle>0){
            (*it)->terminate=1;
            count++;
        }
        if(count>=num)break;
    }
    pool->jobs_mtx.unlock();
    pool->jobs_cond.notify_all();
    return count;
}


struct ArgCallback{
    char name[15];
    int age;
};

void callbacks(void* arg){
    struct ArgCallback* para=(struct ArgCallback*)arg;
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    printf("name=%s, age=%d\n",para->name,para->age);
}

void EXIT(int sig){
    printf("外部信号:%d,主进程退出\n",sig);
    exit(0);
}

int main(int argc, char* args[]){
    nThreadPool* Pool=new nThreadPool;
    nThreadPoolInit(Pool,50);
    for(int i=0;i<500;i++){
        struct NJOB* job=(struct NJOB*)malloc(sizeof(struct NJOB));
        memset(job,0,sizeof(struct NJOB));
        struct ArgCallback* arg=(struct ArgCallback*)malloc(sizeof(struct ArgCallback));
        memset(arg,0,sizeof(struct ArgCallback));
        sprintf(arg->name,"cpp_id_%d",i);
        arg->age=i;
        job->user_data=(void*)arg;
        job->func=callbacks;
        nThreadPoolJobPush(Pool,job);
    }
    int isdestroyed=0;
    while(1){
        char c = getchar();
        if(c=='d'){
            nThreadPoolDestroy(Pool);
            isdestroyed = 1;
        }
        if(isdestroyed!=0&&c=='q')
            break;
    }
    delete Pool;
    return 0;
}

可以考虑做成sdk以便调用。。。

------------------------------------------------补充一个内存池----------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
enum
{
	BLOCKTYPE_START = 0,
	BLOCKTYPE_64 = BLOCKTYPE_START,
	BLOCKTYPE_128,
	BLOCKTYPE_256,
	BLOCKTYPE_512,
	BLOCKTYPE_1024,
	BLOCKTYPE_2048,
	BLOCKTYPE_4096,
	BLOCKTYPE_COUNT
};

const uint64_t pagesize = 4096;
const uint64_t pageconf[][3] = { { 64, 0xFFFFFFFFFFFFFFFF, 64 },
{ 128, 0xFFFFFFFF, 32 }, { 256, 0xFFFF, 16 }, { 512, 0xFF, 8 },
{ 1024, 0xF, 4 }, { 2048, 0x3, 2 }, { 4096, 0x1, 1 } };



struct zv_block_s{ uint64_t sizetype; uint64_t used; void* mem; };
struct zv_slab_s{
	int blockcount;
	struct zv_block_s* empty;
	struct zv_block_s* end;
	struct zv_block_s* slot[BLOCKTYPE_COUNT];
	void* pages;
	struct zv_block_s blocks[0];
};

struct zv_slab_s* zv_slab_init(void* pool, uint64_t size)
{
	struct zv_slab_s* s = (struct zv_slab_s*)pool;
	s->empty = s->blocks;
	uint64_t block_size = pagesize + sizeof(struct zv_block_s);
	s->blockcount = (size - sizeof(struct zv_slab_s)) / block_size;
	s->pages = (char*)pool + sizeof(struct zv_slab_s) + sizeof(struct zv_block_s)*s->blockcount;
	s->empty = s->blocks;
	s->end = s->blocks + s->blockcount;
	int slot_id = -1;
	int slot_group_count = s->blockcount / BLOCKTYPE_COUNT;
    int slot_extra_count = s->blockcount % BLOCKTYPE_COUNT;
	slot_group_count = slot_group_count > 0 ? slot_group_count : 1;
	for (int i = 0; i<s->blockcount; i++)
	{
        if((i-slot_extra_count)<0)
        {
            s->blocks[i].sizetype = pageconf[0][0];
		    s->blocks[i].used = 0;
		    s->blocks[i].mem = (char*)s->pages + i*pagesize;
            continue;
        }
		if ((i-slot_extra_count) % slot_group_count == 0) slot_id++;
		if (slot_id >= BLOCKTYPE_COUNT) slot_id = 0;
		s->blocks[i].sizetype = pageconf[0][0] * (1 << slot_id);
		s->blocks[i].used = 0;
		s->blocks[i].mem = (char*)s->pages + i*pagesize;
	}
	for (int i = 0; i<BLOCKTYPE_COUNT; i++)
    {
        if(i>=1)
            s->slot[i] = s->blocks + slot_extra_count + i*slot_group_count;
        else
		    s->slot[i] = s->blocks + i*slot_group_count;
    }
	return s;
}

void* zv_slab_malloc(struct zv_slab_s* s, uint64_t sz)
{
	if (s == NULL || sz>pagesize)return NULL;
	size_t typ = BLOCKTYPE_START;
	while (sz>pageconf[typ][0])typ++;
	struct zv_block_s* block = s->slot[typ];
	int slot_group_count = s->blockcount / BLOCKTYPE_COUNT;
    if(typ == BLOCKTYPE_64) slot_group_count += s->blockcount % BLOCKTYPE_COUNT;
	for (; slot_group_count>0 && (block->used - pageconf[typ][1]) == 0; slot_group_count--)
		block++;
    if(slot_group_count<=0)return NULL;
	int64_t i = 0, n = pageconf[typ][2];
	while (i<n && (block->used&(0x1 << i)))i++;
	block->used |= (0x1 << i);
	void* ptr = ((char*)block->mem) + i*pageconf[typ][0];
	return ptr;
}

void zv_slab_free(struct zv_slab_s* s, void* ptr)
{
	int64_t page = ((char*)ptr - s->pages) / pagesize;
	struct zv_block_s* b = &(s->blocks[page]);
	int64_t idx = ((char*)ptr - b->mem) / b->sizetype;
	b->used ^= (0x1 << idx);
	return;
}

int main(int argc, char* argv[])
{
	uint64_t psize = 2 * 1024 * 1024;
	void* pool = malloc(psize);
	if (pool == NULL)return - 1;
	struct zv_slab_s* slab = zv_slab_init(pool, psize);
	void* p = zv_slab_malloc(slab, 176);
	void* p1 = zv_slab_malloc(slab, 183);
    zv_slab_free(slab, p);
	free(pool);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值