threadpool.h
#ifndef _THREAD_POOL_H
#define _THREAD_POOL_H
#include <deque>
#include <pthread.h>
#include <string>
#include <string.h>
#include <stdlib.h>
namespace Z1{
class Task{
public:
Task(void *arg = NULL, const std::string taskName="")
: m_ptArg(arg), m_taskName(taskName)
{
}
virtual ~Task(){};
void setArg(void *arg)
{
m_ptArg = arg;
}
virtual int run() = 0;
protected:
std::string m_taskName;
void *m_ptArg;
};
class ThreadPool{
public:
ThreadPool(int threadNum = 10);
~ThreadPool();
public:
size_t addTask(Task *task);
void stop();
int size();
Task* take();
private:
int createThreads();
static void* threadFunc(void * threadData);
private:
ThreadPool & operator = (const ThreadPool&);
ThreadPool(const ThreadPool &);
private:
volatile bool m_bIsRunning;
int m_threadNum;
pthread_t *m_ptThreads;
std::deque<Task *> m_taskQueue;
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
};
};
#endif
threadpool.cpp
#include "threadpool.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
namespace Z1{
ThreadPool::ThreadPool(int threadNum)
{
m_bIsRunning = true;
m_threadNum = threadNum;
m_ptThreads = NULL;
createThreads();
}
ThreadPool::~ThreadPool()
{
stop();
std::deque<Task *>::iterator iter;
for (iter = m_taskQueue.begin(); iter != m_taskQueue.end(); iter++)
{
delete *iter;
}
m_taskQueue.clear();
}
int ThreadPool::createThreads()
{
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL);
m_ptThreads = (pthread_t *)malloc(sizeof(pthread_t) * m_threadNum);
for (int i = 0; i < m_threadNum; i++)
{
pthread_create(&m_ptThreads[i], NULL, threadFunc, this);
}
return 0;
}
size_t ThreadPool::addTask(Task * task)
{
pthread_mutex_lock(&m_mutex);
m_taskQueue.push_back(task);
int size = m_taskQueue.size();
pthread_mutex_unlock(&m_mutex);
pthread_cond_signal(&m_cond);
return size;
}
void ThreadPool::stop()
{
if (!m_bIsRunning)
{
return;
}
m_bIsRunning = false;
pthread_cond_broadcast(&m_cond);
for (int i = 0; i < m_threadNum; i++)
{
pthread_join(m_ptThreads[i], NULL);
}
free(m_ptThreads);
m_ptThreads = NULL;
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_cond);
}
int ThreadPool::size()
{
pthread_mutex_lock(&m_mutex);
int size = m_taskQueue.size();
pthread_mutex_unlock(&m_mutex);
return size;
}
Task* ThreadPool::take()
{
Task* task = NULL;
while (!task)
{
pthread_mutex_lock(&m_mutex);
while (m_taskQueue.empty() && m_bIsRunning)
{
pthread_cond_wait(&m_cond, &m_mutex);
}
if (!m_bIsRunning)
{
pthread_mutex_unlock(&m_mutex);
break;
}
else if (m_taskQueue.empty())
{
pthread_mutex_unlock(&m_mutex);
continue;
}
assert(!m_taskQueue.empty());
task = m_taskQueue.front();
m_taskQueue.pop_front();
pthread_mutex_unlock(&m_mutex);
}
return task;
}
void* ThreadPool::threadFunc(void * threadData)
{
pthread_t tid = pthread_self();
ThreadPool *ptPool = static_cast<ThreadPool *>(threadData);
while (ptPool->m_bIsRunning)
{
Task *task = ptPool->take();
if (!task)
{
printf("thread %lu will exit\n", tid);
break;
}
assert(task);
task->run();
}
return 0;
}
};
threadpoolmain.cpp
#include "threadpool.h"
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <pthread.h>
class MyTask : public Z1::Task{
public:
MyTask(){};
virtual int run()
{
printf("thread[%lu]:%s\n", pthread_self(), (char *)this->m_ptArg);
sleep(1);
return 0;
}
};
int main()
{
char szTmp[] = "myThread";
MyTask taskObj;
taskObj.setArg((void *)szTmp);
Z1::ThreadPool threadPool(10);
for (int i = 0; i < 20; i++)
{
threadPool.addTask(&taskObj);
}
while (1)
{
printf("there are still %d tasks need to process\n", threadPool.size());
if (threadPool.size() == 0)
{
threadPool.stop();
printf("exit from main\n");
exit(0);
}
sleep(2);
}
return 0;
}