线程池实现

介绍

  • 实现一个线程数固定的简单线程池。

代码

  • 在存储任务队列时用到了双向链表来管理。
  • 目录结构
    01

double_llist.h

#ifndef DOUBLE_LLIST__
#define DOUBLE_LLIST__

typedef void d_llist_node_t;
typedef void d_llist_t;

int llist_init(d_llist_t **llist);

typedef int (*compare)(void *a, void *b);
int llist_insert(d_llist_t *llist, void *key, compare cmp);

d_llist_node_t *llist_pop_first(d_llist_t *llist);
d_llist_node_t *llist_pop_last(d_llist_t *llist);

d_llist_node_t *llist_head_look(d_llist_t *llist);
d_llist_node_t *llist_tail_look(d_llist_t *llist);

int llist_destroy(d_llist_t *llist);

typedef int (*traver)(void *node);
int llist_traver(d_llist_t *llist, traver tvr);

// typedef int (*compare)(void *a, void *b);
int llist_check(d_llist_t *llist, compare cmp);

// new
d_llist_node_t *llist_find_node(d_llist_t *llist, void *key, compare cmp);

int llist_delete_node(d_llist_t *llist, void *key, compare cmp);

#endif

double_llist.c

#include <stdio.h>
#include <stdlib.h>

#include "./double_llist.h"


typedef struct llist_node_s{

    void *key;
    struct llist_node_s *prev;
    struct llist_node_s *next;

}llist_node_t;

typedef struct llist_s{

    llist_node_t *head;
    llist_node_t *tail;

}llist_t;




int llist_init(void **llist){

    llist_t *me = NULL;

    me = (llist_t*)malloc(sizeof(*me));
    if(me == NULL){
        return -1;
    }

    me->head = NULL;
    me->tail = NULL;

    *llist = me;

    return 0;
}

/*
    typedef int (*compare)(void *a, void *b);
    compare return value:
        1 : a > b
        -1 : a < b
        0 : a == b
*/
int llist_insert(d_llist_t *llist, void *key, compare cmp){

    llist_t *me = llist;
    llist_node_t *cur = me->head;
    llist_node_t *node_ = NULL;

    node_ = (llist_node_t*)malloc(sizeof(*node_));
    if(node_ == NULL){
        return -1;
    }
    node_->next = NULL;
    node_->prev = NULL;
    node_->key = key;

    int res = 0;

    while(cur != NULL){

        res = cmp(key, cur->key);
        if(res > 0){
            cur = cur->next;
        }else{  // res < 0 || res == 0
            break;
        }

    }


    if(cur == NULL){
        // insert on tail
        // or head = tail = NULL, llist is null
        node_->prev = me->tail;
        node_->next = NULL;
        if(me->tail != NULL){
            me->tail->next = node_;
            me->tail = node_;
        }else{
            me->tail = node_;
        }
        if(me->head == NULL){
            me->head = node_;
        }

    }else if(cur == me->head){
        // insert on head
        node_->next = me->head;
        node_->prev = NULL;
        me->head->prev = node_;
        me->head = node_;

    }else{

        node_->next = cur;
        node_->prev = cur->prev;
        cur->prev->next = node_;
        cur->prev = node_;

    }

    return 0;
}

void *llist_pop_first(void *llist){

    llist_t *me = llist;
    llist_node_t *cur = me->head;

    if(cur == NULL){

        return NULL;

    }else if(cur->next == NULL){

        me->head = NULL;
        me->tail = NULL;

    }else{

        me->head = cur->next;
        me->head->prev = NULL;

    }

    void *ret = cur->key;

    free(cur);

    return ret;
}

void *llist_pop_last(void *llist){

    llist_t *me = llist;
    llist_node_t *cur = me->tail;

    if(cur == NULL){
        return NULL;
    }else if(cur->prev == NULL){
        me->head = NULL;
        me->tail = NULL;
    }else{
        me->tail = cur->prev;
        me->tail->next = NULL;
    }


    void *ret = cur->key;

    free(cur);

    return ret;
}

int llist_destroy(void *llist){

    llist_t *me = llist;
    llist_node_t *cur = me->head, *temp = NULL;

    while(cur != NULL){

        temp = cur->next;

        free(cur->key);
        free(cur);

        cur = temp;

    }

    free(me);

    llist = NULL;

    return 0;
}

/*
typedef int (*traver)(void *node);
*/
int llist_traver(void *llist, traver tvr){

    llist_t *me = llist;
    llist_node_t *cur = me->head;

    while(cur != NULL){

        tvr(cur->key);

        cur = cur->next;
        if(cur){
            printf(" -> ");
        }
    }
    printf("\n");

    return 0;
}


int llist_check(void *llist, compare cmp){

    llist_t *me = llist;
    llist_node_t *cur = me->head;

    if(cur != NULL && cur->next != NULL){
        cur = cur->next;
    }else{
        return 0;
    }

    while(cur != NULL){

        if(cmp(cur->key, cur->prev->key) < 0){
            return -1;
        }
        cur = cur->next;

    }

    return 0;
}




d_llist_node_t *llist_head_look(d_llist_t *llist){

    llist_t *me = llist;

    if(me->head == NULL){
        return NULL;
    }

    return me->head->key;
}
d_llist_node_t *llist_tail_look(d_llist_t *llist){

    llist_t *me = llist;

    if(me->tail == NULL){
        return NULL;
    }

    return me->tail->key;
}


// new
d_llist_node_t *llist_find_node(d_llist_t *llist, void *key, compare cmp){

    llist_t *me = llist;
    llist_node_t *cur = me->head;
    int res = 0;

    

    while(1){
        if (cur == NULL){
            return NULL;
        }

        res = cmp(key, cur->key);
        if(res == 0){
            return cur;
        }

        cur = cur->next;
    }


    return NULL;
}

int llist_delete_node(d_llist_t *llist, void *key, compare cmp){

    llist_t *me = llist;
    llist_node_t *cur = llist_find_node(llist, key, cmp);

    if(cur == NULL){
        return -1;
    }

    if(cur->prev == NULL && cur->next == NULL){

        me->head = NULL;
        me->tail = NULL;
        
    }else if(cur->prev == NULL){
        me->head = cur->next;
        me->head->prev = NULL;
    }else if(cur->next == NULL){
        me->tail = cur->prev;
        me->tail->next = NULL;
    }else{
        cur->next->prev = cur->prev;
        cur->prev->next = cur->next;
    }

#if 1
    free(cur->key);
    free(cur);
#endif

    return 0;
}

thread_pool.h

#ifndef THREAD_POOL__
#define THREAD_POOL_

#include <pthread.h>

#include "../double_llist/double_llist.h"

typedef struct thread_pool_st{

    int thread_num;
    int stop;
    
    d_llist_t *task;
    pthread_mutex_t tast_mutex;
    pthread_cond_t task_cond;

}thread_pool_t;


typedef int (*task_callback)(void *);
typedef struct task_st{

    task_callback task_cb;
    void *arg;

}task_t;

// 线程池的初始化以及线程创建
int thread_pool_init(thread_pool_t **pool, int thread_num);

// 添加任务
int task_post(thread_pool_t *pool, task_callback task_cb, void *arg);

// 线程池的销毁
int thread_pool_destroy(thread_pool_t *pool);


#endif

thread_pool.c

#include <stdio.h>
#include <stdlib.h>

#include <pthread.h>
#include <unistd.h>
#include <sys/time.h>

#include "./thread_pool.h"

static int mytraver(void *data);

static void *runner(void *arg){

    thread_pool_t *me = arg;

    while(1){

        pthread_mutex_lock(&me->tast_mutex);
        
        while(llist_head_look(me->task) == NULL){

            pthread_cond_wait(&me->task_cond, &me->tast_mutex);
            if(me->stop == 1){
                break;
            }

        }


        task_t *task_cur = llist_pop_first(me->task);

        pthread_mutex_unlock(&me->tast_mutex);

        if(task_cur == NULL){
            break;
        }

        task_cur->task_cb(task_cur->arg);

        free(task_cur->arg);
        free(task_cur);

    }

    printf("thread %lu exit.\n", pthread_self());
    pthread_exit(0);
}

static int pool_thread_create(thread_pool_t *pool){

    thread_pool_t *me = pool;
    pthread_t pid;

    int i = 0;
    for(i = 0; i < me->thread_num; i++){

        if(pthread_create(&pid, NULL, runner, me) != 0){
            return -1;
        }
        printf("create thread[%d] success.\n", i + 1);

    }


    return 0;
}

int thread_pool_init(thread_pool_t **pool, int thread_num){

    thread_pool_t *me = (thread_pool_t*)malloc(sizeof(*me));
    if(me == NULL){
        return -1;
    }

    me->thread_num = thread_num;
    int ret = 0;
    ret = llist_init(&me->task);
    if(ret){
        return -2;
    }
    me->stop = 0;
    if(pthread_mutex_init(&me->tast_mutex, NULL) != 0){
        return -3;
    }
    if(pthread_cond_init(&me->task_cond, NULL) != 0){
        return -3;
    }

    pool_thread_create(me);


    *pool = me;

    return 0;
}

static int mycompare(void *a, void *b){

    return 1;
}

static int mytraver(void *data){

    task_t *task = data;

    printf("[%d]", *(int*)task->arg);

    return 0;
}

int task_post(thread_pool_t *pool, task_callback task_cb, void *arg){

    thread_pool_t *me = pool;

    if(me->stop == 1){
        printf("thread_pool stop will,can't post task!\n");
        return 1;
    }

    task_t *cur = (task_t*)malloc(sizeof(*cur));
    if(cur == NULL){
        return -1;
    }

    cur->task_cb = task_cb;
    cur->arg = arg;

    pthread_mutex_lock(&me->tast_mutex);
    int ret =  llist_insert(me->task, cur, mycompare);
    pthread_mutex_unlock(&me->tast_mutex);

    if(ret == 0){
        // llist_traver(me->task, mytraver);
        pthread_cond_signal(&me->task_cond);
    }else{
        return -2;
    }

    return 0;
}


int thread_pool_destroy(thread_pool_t *pool){
    
    thread_pool_t *me = pool;

    me->stop = 1;

    pthread_mutex_lock(&me->tast_mutex);
    while(1){
        if(llist_head_look(me->task) == NULL){
            break;
        }else{
            pthread_cond_broadcast(&me->task_cond);
            struct timeval now;
            struct timespec outtime;
            gettimeofday(&now, NULL);
            outtime.tv_sec = now.tv_sec + 5;      // s
            outtime.tv_nsec = now.tv_usec * 1000; //微妙转为纳秒
            pthread_cond_timedwait(&me->task_cond, &me->tast_mutex, &outtime);
        }
    }
    pthread_mutex_unlock(&me->tast_mutex);

    pthread_cond_broadcast(&me->task_cond);

    return 0;
}

test.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "./thread_pool.h"

int myprint(void *arg){

    int *p = arg;

    printf("num = %d\n", *p);

    sleep(1);

    return 0;
}

int main(){

    thread_pool_t *pool;
    int ret = 0;

    ret = thread_pool_init(&pool, 10);
    if(ret){
        puts("init()");
        exit(1);
    }


    int i = 0;
    int res = 0;
    for(i = 0; i < 1024; i++){
        
        int *p = (int*)malloc(sizeof(*p));

        *p = i + 1;

        res = task_post(pool, myprint, p);
#if 0
        if(res){
            printf("task[%d] post error.\n", i + 1);
        }else{
            printf("task[%d] post success.\n", i + 1);
        }
#endif

        // sleep(1);
    }

    // pause();

    thread_pool_destroy(pool);

    pause();

    exit(0);
}

总结

已实现功能

  1. 线程池的初始化以及销毁;
  2. 任务的添加。

待实现功能

  1. 对线程数的动态增加以及减少;
  2. 线程池的销毁有点麻烦,因为没有存储线程的 id 信息,可以优化一下。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值