KMThreadPool: 4 – Thread Pool Step 2: SettingUp the Threads
来源:互联网 发布:pc游戏优化不好 编辑:程序博客网 时间:2024/05/29 18:03
4 – Thread Pool Step 2: SettingUp the Threads
KMTask
Lets go back to the heart of thethread pool (or to those in denial, the liver): The tasks. To keep everythingmanaged and such, we’ve encapsulated theKMTaskFunc
and IKMTaskData*
inside the KMTask
class, just so we can keep things managed(and modular; so you can add new functionality like dependencies or referencesor contexts or whatever you’d like in the future).
class KMTask
{
private:
KMTaskFunc m_task;
IKMTaskData* m_data;
public:
KMTask(KMTaskFunc task, IKMTaskData* data)
{
m_task = task;
m_data = data;
}
~KMTask()
{
if(m_data!=NULL)
delete m_data;
m_data = NULL;
m_task = NULL;
}
KMTaskFunc GetTask() { return m_task; }
IKMTaskData* GetData() { return m_data; }
protected:
};
Not so bad. Just manages the datafor us. This way we don’t really have to explicitly delete theIKMTaskData*
inside our task.
KMThread
Here is the logic behind ourthreads: 1. Create the thread when the threadpool starts up, 2. Idle until wefind a task in the thread pool, 3. Run the task, 4. When we finish, clean upthe memory, 5. Goto 2 (6. Beat up the guy who wrote this tutorial for using agoto).
Here is a quick rundown of themembers in the threads:
KMThreadpool* m_pthreadpool;
HANDLE m_hthread;
KMLock m_lock;
KMTask* m_ptask;
bool m_brunning;
bool m_bpaused;
unsigned int m_uithreadID;
DWORD m_dwexit;
m_pthreadpool
is apointer to the actual thread pool class, and you’ll see why we need that injust a minute.m_hthread
is a handle (a kind ofsmart pointer) to the thread in the Windows API.m_lock
is the oneone lock we need to protect executing our task with.m_ptask
is thetask we get from the thread pool.m_brunning
is a flagthat’s set to true once the thread initializes successfully, and false if itfails or gets shut down.m_bpaused
is… uhh…legacy code! (meaning: code I forgot to delete, but isn’t breaking anything)m_uithreadID
is anID assigned from the Windows API.m_dwexit
is theexit code returned once the thread shuts down for any reason.
Now there are a few accessorfunctions and such, but we want to focus on 4 main functions:
public:
void Begin();
void End();
DWORD ThreadProc();
protected:
static unsigned __stdcall cThreadProc(LPVOID _pThis)
{
return ((KMThread*)_pThis)->ThreadProc();
}
Now, you see cThreadProc()
. This function is called by the WindowsAPI when you create the thread. The API will be calling this function, and thisfunction callsThreadProc()
, and ThreadProc()
runs our task. Indirection out thewazzoo, baby!
Next we have Begin()
. Nothing too special here for anyone whohas ever created threads before. We grab the instance of our thread pool(because it’s a singleton), then we create our thread using_beginthreadex()
, and if m_hthread
isn’t NULL
, then it was a success! Once again, verysimple.
void KMThread::Begin()
{
// Set our thread pool
m_pthreadpool = KMThreadpool::getInstance();
#if defined( _WIN32 )
// Start the thread.
m_hthread = (HANDLE)_beginthreadex( NULL,
0,
&cThreadProc,
(void*)this,
0,
&m_uithreadID );
m_brunning = true;
if( m_hthread == NULL )
{
// You can add extra error-handling here.
m_brunning = false;
}
#endif /* defined( _WIN32 ) */
}
And for every Begin()
, there must be an End()
.
void KMThread::End()
{
#if defined( _WIN32 )
if( m_hthread != NULL )
{
m_brunning = false;
WaitForSingleObject( m_hthread, INFINITE );
DWORD ExitCode;
GetExitCodeThread( m_hthread, &ExitCode );
m_dwexit = ExitCode;
CloseHandle( m_hthread );
m_hthread = NULL;
}
#endif /* defined( _WIN32 ) */
}
People familiar with somemultithreading experience may throw up a red flag and say “Hey! Why aren’t youusing_endthreadex()
? Duh!” Well, Mr. NonBeliever, _endthreadex()
in the Win32 API doesnot closethe handle. This explicit way of closing the thread allows me to free up allnecessary memory and allows me to get the exit codes and such. And for newbiesto threading, thatWaitForSingleObject()
function is also part of the Win32 API.It waits for the handle to the thread to finish its current cycle (for anINFINITE
amount of time), and stops it fromcontinuing so we can manipulate the handle (in this case, closing the handle).
The last major function in thisclass is the full-on assembily of the circulatory system of the thread pool:TheThreadProc()
function. This function is in charge of processing the actual task andgrabbing a new task once we finish. However, it’s not as simple as just run thetask and get a new one from the queue. We have to be safe and slick when we dothis. Here’s a look at the code:
DWORD KMThread::ThreadProc()
{
m_ptask = NULL;
// The main thread-loop. As long as this loop
// is running, the thread stays alive.
while(m_brunning)
{
Sleep(1);
// The thread pauses when it finishes a task.
// Adding a task resumes it.
if(m_ptask != NULL)
{
m_lock.Lock();
{
KMTaskFunc task = m_ptask->GetTask();
IKMTaskData* data = m_ptask->GetData();
// Run the actual task
if(task != NULL && data != NULL)
{
task(data);
}
// Task is complete.
delete m_ptask;
m_ptask = NULL;
}
m_lock.Unlock();
}
// If we're finished with our task, grab a new one.
if(m_ptask == NULL && m_pthreadpool->IsProcessing() == true)
{
m_ptask = m_pthreadpool->m_qtaskList.pop();
}
}
return 0;
}
The thread is almost set up asits own program, with the main thread loop in there. It’s set up so as long asthe thread is running (set by eitherbegin()
, end()
or by the thread pool), it will do thework inside.
First thing we do inside this loop is Sleep(1)
. When I originally wrote the thread pool,I wasn’t callingSleep()
, and all my threads became processor hogs. If you downloaded the code orare writing it yourself, go ahead and comment out theSleep()
call and watch your computer burn!
Next, we check to see if the m_ptask
is NULL
.
- If it isn’t, then we go ahead and process it. We lock around the tasks to protect the data from getting possibly modified by another thread, and after we call the task (like you would with any normal function) we go and clean up the data.
- If it is, check the thread pool and get the next task in the queue.
And that’s our threads! Nifty!Now on to the main brain of the outfit… The interface for all thismultithreaded goodness…
转自:http://keithmaggio.wordpress.com/code/c-win32-thread-pool-manager/4-step2/
- KMThreadPool: 4 – Thread Pool Step 2: SettingUp the Threads
- KMThreadPool: 6 – Thread Pool Step 4:How to Use
- KMThreadPool: 5 – Thread Pool Step 3:Enter Thread Pool
- KMThreadPool: 3 – Thread Pool Step 1: Utilities, Locks and Algorithms
- The CLR's Thread Pool
- KMThreadPool: 2 – Concepts And Facts
- KMThreadPool: 7 – Conclusion
- Python thread pool similar to the multiprocessing Pool?
- Java: Threads pool
- Thread Pool
- Thread Pool
- Thread Pool
- thread pool
- thread pool
- thread pool
- thread pool
- Thread Pool
- thread pool
- Android实现数据存储技术
- Java中的自增操作符与中间缓存变量机制
- 山东举报食安犯罪者最高可奖励30万-山东-食品犯罪
- linux系统下,11款常见远程桌面控制软件
- Windows xp
- KMThreadPool: 4 – Thread Pool Step 2: SettingUp the Threads
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析
- arm 汇编 跑马灯
- MYSQL 主从同步配置
- KMThreadPool: 5 – Thread Pool Step 3:Enter Thread Pool
- IOS程序后台运行及多任务
- Bitnami redmine 安装后查看数据库以及更改url
- HTTP请求头和相应头的详细介绍
- 上海撞死5名养护工肇事者称捡眼镜时打歪方向-撞死-养护工