richardli79

导航

以前用过的的一个线程池代码

#ifndef __THRMGR_H__
#define __THRMGR_H__

#include 
<pthread.h>
#include 
<sys/time.h>
#include 
<stdio.h>
#include 
<time.h>
#include 
<errno.h>
#include 
"memory.h"
#include 
<stdlib.h>

#define FALSE (0)
#define TRUE (1)

typedef 
struct work_item_tag 
{
    
struct work_item_tag *next;
    
void *data;
    
struct timeval time_queued;
}
work_item_t;
 
typedef 
struct work_queue_tag 
{
    work_item_t 
*head;
    work_item_t 
*tail;
    
int item_count;
}
work_queue_t;

typedef 
enum 
{
    POOL_INVALID,
    POOL_VALID,
    POOL_EXIT,
}
pool_state_t;

typedef 
struct threadpool_tag 
{
    pthread_mutex_t pool_mutex;
    pthread_cond_t pool_cond;
    pthread_attr_t pool_attr;
 
    pool_state_t state;
    
int thr_max;
    
int thr_alive;
    
int thr_idle;
    
int idle_timeout;
 
    
void (*handler)(void *);
 
    work_queue_t 
*queue;
}
threadpool_t;

threadpool_t 
*thrmgr_new(int max_threads, int idle_timeout, void (*handler)(void *));
void thrmgr_destroy(threadpool_t *threadpool);
int thrmgr_dispatch(threadpool_t *threadpool, void *user_data);

#endif

work_queue_t 
*work_queue_new()
{
    work_queue_t 
*work_q = NULL;
    work_q 
= (work_queue_t *) malloc(sizeof(work_queue_t));
    work_q
->head = work_q->tail = NULL;
    work_q
->item_count = 0;
    
return work_q;
}


void work_queue_add(work_queue_t *work_q, void *data)
{
    work_item_t 
*work_item;

    
if (!work_q) 
    
{
        
return;
    }

    work_item 
= (work_item_t *) malloc(sizeof(work_item_t));
    work_item
->next = NULL;
    work_item
->data = data;
    gettimeofday(
&(work_item->time_queued), NULL);
 
    
if (work_q->head == NULL) 
    
{
        work_q
->head = work_q->tail = work_item;
        work_q
->item_count = 1;
    }
 
    
else 
    
{
        work_q
->tail->next = work_item;
        work_q
->tail = work_item;
        work_q
->item_count++;
 }

 
return;
}


void *work_queue_pop(work_queue_t *work_q)
{
    work_item_t 
*work_item;
    
void *data;
 
    
if (!work_q || !work_q->head) 
    
{
        
return NULL;
    }

    work_item 
= work_q->head;
    data 
= work_item->data;
    work_q
->head = work_item->next;
    
if (work_q->head == NULL) 
    
{
        work_q
->tail = NULL;
    }

    free(work_item);
    
return data;
}


void thrmgr_destroy(threadpool_t *threadpool)
{
    
if (!threadpool || (threadpool->state != POOL_VALID)) 
    
{
        
return;
    }

    
if (pthread_mutex_lock(&threadpool->pool_mutex) != 0
    
{
        printf(
"!Mutex lock failed\n");
        exit(
-1);
    }

    threadpool
->state = POOL_EXIT;
 
 
/* wait for threads to exit */
    
if (threadpool->thr_alive > 0
    
{
        
/*通知兄弟们收工*/
        
if (pthread_cond_broadcast(&(threadpool->pool_cond)) != 0
        
{
            pthread_mutex_unlock(
&threadpool->pool_mutex);
            
return;
        }

    }

    
while (threadpool->thr_alive > 0
    
{
        
/*原来是这位老兄负责等最后一名兄弟的信号啊*/
        
if (pthread_cond_wait (&threadpool->pool_cond, &threadpool->pool_mutex) != 0
        
{
            pthread_mutex_unlock(
&threadpool->pool_mutex);
            
return;
        }

    }

    
if (pthread_mutex_unlock(&threadpool->pool_mutex) != 0
    
{
        printf(
"!Mutex unlock failed\n");
        exit(
-1);
    }

 
    pthread_mutex_destroy(
&(threadpool->pool_mutex));
    pthread_cond_destroy(
&(threadpool->pool_cond));
    pthread_attr_destroy(
&(threadpool->pool_attr));
    free(threadpool
->queue);
    free(threadpool);
    
return;
}


threadpool_t 
*thrmgr_new(int max_threads, int idle_timeout, void (*handler)(void *))
{
    threadpool_t 
*threadpool = NULL;
 
    
if (max_threads <= 0
    
{
         
return NULL;
    }

 
    threadpool 
= (threadpool_t *) malloc(sizeof(threadpool_t));

    threadpool
->queue = work_queue_new();
    
if (NULL == threadpool->queue) 
    
{
        free(threadpool);
        
return NULL;
    }
 
    threadpool
->thr_max = max_threads;
    threadpool
->thr_alive = 0;
    threadpool
->thr_idle = 0;
    threadpool
->idle_timeout = idle_timeout;
    threadpool
->handler = handler;
 
    pthread_mutex_init(
&(threadpool->pool_mutex), NULL);
    
if (pthread_cond_init(&(threadpool->pool_cond), NULL) != 0
    
{
        free(threadpool
->queue);
        free(threadpool);
        
return NULL;
    }

  
    
if (pthread_attr_init(&(threadpool->pool_attr)) != 0
    
{
        free(threadpool
->queue);
        free(threadpool);
        
return NULL;
    }

 
    
if (pthread_attr_setdetachstate(&(threadpool->pool_attr), PTHREAD_CREATE_DETACHED) != 0
    
{
        free(threadpool
->queue);
        free(threadpool);
        
return NULL;
    }

    threadpool
->state = POOL_VALID;

    
return threadpool;
}


/*工作线程.该工作线程遍历工作链表,如果有活干就干,没活干就等活干,难怪叫民工*/

void *thrmgr_worker(void *arg)
{
    threadpool_t 
*threadpool = (threadpool_t *) arg;
    
void *job_data;
    
int retval, must_exit = FALSE;
    
struct timespec timeout;
 
    
/* loop looking for work */
    
for (;;) 
    
{
        
if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0
        
{
            
/* Fatal error */
            printf(
"!Fatal: mutex lock failed\n");
            exit(
-2);
        }

        timeout.tv_sec 
= time(NULL) + threadpool->idle_timeout;
        timeout.tv_nsec 
= 0;
        threadpool
->thr_idle++;
        
while (((job_data=work_queue_pop(threadpool->queue)) == NULL)&& (threadpool->state != POOL_EXIT)) 
        
{
            
/* Sleep, awaiting wakeup ,注意,民工等一段时间,如果没有活干就结束该线程*/
            retval 
= pthread_cond_timedwait(&(threadpool->pool_cond),&(threadpool->pool_mutex), &timeout);
            
if (retval == ETIMEDOUT)
            
{
                must_exit 
= TRUE;
                
break;
            }

        }

        threadpool
->thr_idle--;//要干活了,闲着的民工少了一位
        if (threadpool->state == POOL_EXIT) 
        
{
            must_exit 
= TRUE;
        }

  
        
if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0
        
{
            
/* Fatal error */
            printf(
"!Fatal: mutex unlock failed\n");
            exit(
-2);
        }

        
if (job_data) 
        
{
            threadpool
->handler(job_data);
        }
 
        
else if (must_exit) 
        
{
            
/*如果没有等到活或者要结束整个线程池时,该线程收工*/
            
break;
        }

    }

    
if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0
    
{
        
/* Fatal error */
        printf(
"!Fatal: mutex lock failed\n");
        exit(
-2);
    }

    threadpool
->thr_alive--;//活干完了,该走人了(人又少了一个)
    if (threadpool->thr_alive == 0
    
{
        
/* signal that all threads are finished */
        pthread_cond_broadcast(
&threadpool->pool_cond);//人都跑光了,谁还听得到这个信号?多次一举吗?
    }

    
if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0
    
{
        
/* Fatal error */
        printf(
"!Fatal: mutex unlock failed\n");
        exit(
-2);
    }

    
return NULL;
}


/*创建一个工作线程,如果目前有等待条件信号的工作线程,则唤醒该工作线程处理数据*/
int thrmgr_dispatch(threadpool_t *threadpool, void *user_data)
{
    pthread_t thr_id;
    
    
if (!threadpool) 
    
{
        
return FALSE;
    }


    
/* Lock the threadpool */
    
if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0
    
{
        printf(
"!Mutex lock failed\n");
        
return FALSE;
    }


    
if (threadpool->state != POOL_VALID)
    
{
        
if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0
        
{
            printf(
"!Mutex unlock failed\n");
            
return FALSE;
        }

        
return FALSE;
    }

    work_queue_add(threadpool
->queue, user_data);

    
/*只有当目前没有线程idle且目前生成的线程数小于最大线程要求时,创建新的线程*/
    
if ((threadpool->thr_idle == 0)&&(threadpool->thr_alive < threadpool->thr_max)) 
    
{
        
/* Start a new thread */
        
if (pthread_create(&thr_id, &(threadpool->pool_attr),thrmgr_worker, threadpool) != 0
        
{
           printf(
"!pthread_create failed\n");
        }
 
        
else
        
{
            threadpool
->thr_alive++;
        }

    }


    
/*释放条件信号,如果有正在等待该信号的线程,则该线程运行*/
    pthread_cond_signal(
&(threadpool->pool_cond));

    
if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0)
    
{
        printf(
"!Mutex unlock failed\n");
        
return FALSE;
    }

    
return TRUE;
}

标准的一个在Linux下用的线程池代码,估计很多人都用得这个,改天把java的那个也贴上来。就怕忘了。

posted on 2007-01-07 20:41  Richard  阅读(391)  评论(0编辑  收藏  举报