In many of our applications we use multi threading for better performance. Most of us already knows and using multi threading applications. And we know that thread creation is a resource intensive job. It is always better to reuse the threads, and most of us do this also. This article talks about such a thread pooling (worker thread) architecture. It will be great if you can provide let me know about any bugs that are found and any improvements that can be done to this.
Architecture in briefThe main architecture of the thread pool is given below in the class diagram.
As you can see in the above class diagram the application has mainly three classes, they are
CThPool
class : This is the main thread pool class. To use thread pool you have to only create an instance of this class. CThread
class : This class encapsulates one thread. You don't have to create any instance of this class. The CThPool
class will return a CThread
class, which you should use. You should not also destroy the CThread
object that you received from the CThPool
class instance.CThTarget
: This is the base class of all the target objects which can be passed to the CThread
class as target. This is an abstract class with run()
as the pure virtual method. You should implement the run()
in your inherited class. As shown in the class diagram for the class CYourClass
.To use the thread pool code we have to do the following
CThpool *m_pThPool; m_pThPool = new CThPool();
m_pThPool->setMaxPoolSize(10);
CThTarget
class and implement the pure virtual function void
run
(). Refer the sample code below
class CThTargetSuper : public CThTarget { public: CThTargetSuper(); virtual ~CThTargetSuper(); void run(); } void CThTargetSuper::run() { }
CThTargetSuper* pTarget = new CThTargetSuper();
run()
function of your class. Then get an instance of CThread
class from the pool by calling the function getThread()
. Then call the setTarget()
function of the CThread
instance you received and pass the reference of your inherited CThTarget
class.
CThread * pTh=NULL; pTh = m_pThPool->getThread(); if( pTh!=NULL) pTh->setTarget(pTarget);
Note : As you see in the above code the CThread
instance received from the CThPool::getThread()
function may return NULL
. This is in case of all the threads are busy and no free thread is available and the pool's current size is already achieved the Max pool size. If you want the job should be processed then you can try again after some time. The code can be modified as follows. But if this code is executed by the main GUI thread then the while loop may cause problem if the threads are busy for long time. In such cases this code should be executed in a different thread.
CThread * pTh=NULL; pTh = m_pThPool->getThread(); while(pTh ==NULL) { Sleep(100); pTh = m_pThPool->getThread(); } if( pTh!=NULL) pTh->setTarget(pTarget);
CThread::setTarget()
function call the run()
function of the CThTarget
type object will run in a separate thread. The thread will automatically return to the pool when the run()
function finishes.
Note : Once the thread will be completed the CThTarget
object cannot be used again. This is because once the run()
function finishes the thread deletes the instance of the CThTarget
. If you want to use the CThTarget
object later then you have to tell the thread explicitly by setting the auto delete flag of CThTarget
to FALSE
as given in the code below.
CThTargetSuper* pTarget = new CThTargetSuper(); pTarget->setAutoDelete(FALSE);
The default value is TURE
. You can check this at any time by calling AutoDelete()
. It returns TRUE
if the flag is set as TRUE
.
Never call setTarget()
again on the same CThread
instance that you received from the last getThread()
object. Always use getThread()
on CThPool
instance to get a CThread
object and then use setTarget()
on that object only once.
Some times our application may need let 100 threads but most of the time the required thread is less than 20. In that case it is no need to create and keep 100 threads always in the pool. In such cases we can define the maximum free pool size to 20.This will make sure that not more than 20 idle threads will be available in the free pool. If required more number of threads will be created as on demand. Sample code is given below.
m_pThPool = new CThPool(); m_pThPool->setMaxPoolSize(100); m_pThPool->setMaxFreePoolSize(20);Getting Statistics
Some times we may require statistics to know at any instance of time how many threads are busy and how many threads are free, what is the pool size now, etc. etc. We can get such information by calling some methods of pool. In the sample application the statistics are also used. The functions that are available to get the statistical information are
int CThPool::getCurPoolSize() int CThPool::getMaxPoolSize() int CThPool::getMaxFreePoolSize() int CThPool::getFreePoolSize()About The Demo Program
The demo program uses one thread pool. Initially the pool has started with one thread. And the Max pool size is 5. And the maximum free thread size is 2. In the demo program CThTargetSuper
is the class, which extends CThTarget
and implement the run()
method. The run method simply increments the progress bar after sleeping 100 ms till it reaches the end. If more number of threads will be assigned then the progress bar will move fast. The run()
methods ends when the progress bar reaches the end of the bar. And the after that the instance of the CThTargetSuper
gets deleted by the thread (As the Auto Delete flag is TRUE
by default) and the threads returns to the free pool and remains in suspended mode till another work get assigned. The thread may also exit if the number of threads that are present in the free pool is more than the maximum limit.
After you start the program first create the pool by clicking the CreatePool button. Then you can click on the AssignThread button to assign a new thread. You can not assign more threads than the Max Pool size. The current number of threads busy in the pool is displayed in the statistics along with the idle threads and max pool size. You can change the the maximum pool size by clicking the button "+" or "-" . (Upper limit is defined as 20). You can also change the maximum free pool size by clicking the corresponding "+" / "-" button. You can also press the Refresh button to refresh the statistics. The statistics also gets automatically updated around every 2 seconds.
To repeat the process click on the Reset button so that the progress bar will be reset to initial position. And you can assign the threads again to increase the progress bar's progress.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.3