Self-written thread pool class (using C ++, pure API, mutex, event)

Source: Internet
Author: User

A computer network test requires a file transfer program. Because the previously written thread and socket classes were lost (the dormitory computer was stolen), I have simply written a thread pool to rewrite these classes, c ++ STL and pure API are used. In addition, to ensure the Thread class itself is thread safe, I also use the mutex in winapi. The join method is added to the Thread class in the same way as the C # class library. The thread that calls the join method of the thread object will wait for the thread object until the execution is completed. The following is the source code.

//// // Mythread. h //////////////////////////////////////

# Ifndef _ mythread_h _
# DEFINE _ mythread_h _
# Include "myexception. H"
# Include <windows. h>
# Include <list>
Using namespace STD;

// Forward Declaration
Class cmythread; // Thread class
Class cmythreadpool; // thread pool class
Class cmythreadexp; // thread exception class

# Define mythreadproc lpthread_start_routine

// Thread status Enumeration
Enum mythreadstatus
{
Threadrun, // run
Threadpause, // pause
};
// Thread class, which can dynamically change the execution function
Class cmythread
{
Struct mythreadparam
{
Lpthread_start_routine proc; // user thread function
Void * lpparam; // user thread Parameter
Cmythread * pcmythread; // Thread class Object
};
Public:
// Construct, Proc thread function
Cmythread ();
// Structure
~ Cmythread ();
// Running thread
Bool run ();
// Pause the thread
Bool pause ();
// The thread that calls the join operation will be blocked until the execution of the thread is completed.
Void join ();
// Set the functions run by the thread and the parameters to be passed to the thread
Void setproc (lpthread_start_routine proc, void * lpparam );

Protected:
Cmythread (cmythread &){}
// Functions actually run by the thread
Static DWORD winapi realthreadproc (void * lpparam );
Friend class cmythreadpool;

Protected:
Handle m_hthread;
DWORD m_id;
Handle m_hevt;
Mythreadparam m_param;
Mythreadstatus m_status;
Handle m_hgp;
};

// Thread pool class
Class cmythreadpool
{
Public:
// Construct, the number of threads in initnum Initial Condition
Cmythreadpool (INT initnum );
// Structure
~ Cmythreadpool ();
// Request the thread to perform work, Proc work function, lpparam work function parameter, run whether to run immediately, return the thread ID
DWORD dowork (lpthread_start_routine proc, void * lpparam, bool run = true );
// Running thread, Id thread ID
Bool run (dword id );
// Pause the running thread, Id thread ID
Bool pause (dword id );
// Adjust the thread pool size to size, and return the adjusted thread pool size
Unsigned setsize (unsigned size); // when decrease num, its dangerous

Protected:
List <cmythread *> m_lst;
};

// Thread exception type Enumeration
Enum enummythreadexp
{
Expcreatethread = 0,
Expterminatethread,
Expresumethread,
Expsuspendthread,
Expcreateevent,
Expcreatemutex,
};
// Thread exception class
Class cmythreadexp: Public cmyexception
{
Public:
Cmythreadexp (enummythreadexp exp, cmythread * pobj );
~ Cmythreadexp ();
Void getinfo ();
Enummythreadexp m_exp;
Cmythread * m_pobj;
};

# Endif // _ mythread_h _

/// // Mythread. CPP //////////////////////////////////

# Include "mythread. H"
# Include <iostream>
Using namespace STD;

Cmythreadexp: cmythreadexp (enummythreadexp, cmythread * pobj)
: M_exp (exp), m_pobj (pobj)
{
Getinfo ();
Showexp ();
}
Cmythreadexp ::~ Cmythreadexp ()
{
}
Void cmythreadexp: getinfo ()
{
Sprintf (m_strinfo, "/ncmythread exception when % P execute", (void *) (m_pobj ));
Switch (m_exp)
{
Case expcreatethread: strcat (m_strinfo, "createthread ()"); break;
Case expterminatethread: strcat (m_strinfo, "terminatethread ()"); break;
Case expresumethread: strcat (m_strinfo, "resumethread ()"); break;
Case expsuspendthread: strcat (m_strinfo, "suspendthread ()"); break;
Case expcreateevent: strcat (m_strinfo, "createevent ()"); break;
Case expcreatemutex: strcat (m_strinfo, "createmutex ()"); break;
}
Char temp [100];
Sprintf (temp, "/nerror code = % d", getlasterror ());
Strcat (m_strinfo, temp );
}
/*************************************** **************************************** ***************/
Cmythread: cmythread ()
: M_hthread (null), m_status (threadpause), m_hevt (0), m_hctx (0)
{
M_hthread = createthread (0, 0, (lpthread_start_routine) (cmythread: realthreadproc ),
(Void *) & m_param, create_suincluded, & m_id );
If (m_hthread = NULL) // fail to create thread
{
Cmythreadexp (expcreatethread, this );
Throw; // construct exception
}
M_param.proc = NULL;
M_param.lpparam = NULL;
M_param.pcmythread = this;

M_hevt = createevent (0, false, false, 0); // auto reset
If (m_hevt = 0)
{
Closehandle (m_hthread );
Cmythreadexp (expcreateevent, this );
Throw; // construct exception
}
M_hctx = createmutex (0, 0, 0 );
If (m_hctx = 0) // fail to create mutex
{
Unsigned long I = getlasterror ();
Closehandle (m_hevt );
Closehandle (m_hthread );
Cmythreadexp (expcreatemutex, this );
Throw; // construct exception
}
}
Cmythread ::~ Cmythread ()
{
Closehandle (m_hgp );
If (terminatethread (m_hthread,-1) = 0) // fail to terminate
Cmythreadexp (expterminatethread, this );
}
Bool cmythread: Run ()
{
Waitforsingleobject (m_hctx, infinite); // get mutex
If (m_status = threadpause)
If (resumethread (m_hthread) =-1) // fail to resume
{
Cmythreadexp (expresumethread, this );
Releasemutex (m_hctx); // release mutex
Return false;
}
M_status = threadrun;
Releasemutex (m_hctx); // release mutex
Return true;
}
Bool cmythread: Pause ()
{
Waitforsingleobject (m_hctx, infinite); // get mutex
If (m_status = threadrun)
If (suspendthread (m_hthread) =-1) // fail to suspend
{
Cmythreadexp (expsuspendthread, this );
Releasemutex (m_hctx); // release mutex
Return false;
}
M_status = threadpause;
Releasemutex (m_hctx); // release mutex
Return true;
}
Void cmythread: Join ()
{
Waitforsingleobject (m_hevt, infinite );
}
Void cmythread: setproc (lpthread_start_routine proc, void * lpparam)
{
Waitforsingleobject (m_hctx, infinite); // get mutex
M_param.proc = proc;
M_param.lpparam = lpparam;
Releasemutex (m_hctx); // release mutex
}
DWORD winapi cmythread: realthreadproc (void * lpparam)
{
Lpthread_start_routine proc;
Mythreadparam * PP = (mythreadparam *) lpparam;
While (true)
{
Proc = PP-> proc;
If (Proc)
(* Proc) (PP-> lpparam );
PP-> proc = NULL; // clear Function
PP-> lpparam = NULL; // clear Param
PP-> pcmythread-> pause (); // pause automatic
Setevent (PP-> pcmythread-> m_hevt );
}
}
/*************************************** **************************************** ***************/
Cmythreadpool: cmythreadpool (INT initnum)
{
Cmythread * PT;
For (INT I = 0; I <initnum; I ++)
{
PT = new cmythread;
M_lst.push_back (PT );
}
}
Cmythreadpool ::~ Cmythreadpool ()
{
List <cmythread *>: iterator it = m_lst.begin ();
List <cmythread *>: iterator ite = m_lst.end ();
For (; it! = Ite; it ++) // terminate all thread
{
Delete (* it );
}
}
DWORD cmythreadpool: dowork (lpthread_start_routine proc, void * lpparam, bool run)
{
List <cmythread *>: iterator it = m_lst.begin ();
List <cmythread *>: iterator ite = m_lst.end ();
For (; it! = Ite; it ++) // is there a idle thread?
{
If (* It)-> m_param.proc = NULL
& (* It)-> m_status = threadpause
)
{
(* It)-> setproc (Proc, lpparam );
If (run) // run at once
(* It)-> Run ();
Return (* It)-> m_id;
}
}
// No idle thread
Cmythread * PT = new cmythread; // create a new thread
M_lst.push_back (PT );
Pt-> setproc (Proc, lpparam );
If (run)
Pt-> Run ();
Return Pt-> m_id;
}
Bool cmythreadpool: Run (dword id)
{
List <cmythread *>: iterator it = m_lst.begin ();
List <cmythread *>: iterator ite = m_lst.end ();
For (; it! = Ite; it ++)
{
If (* It)-> m_id = ID)
Return (* It)-> Run ());
}
Return false;
}
Bool cmythreadpool: Pause (dword id)
{
List <cmythread *>: iterator it = m_lst.begin ();
List <cmythread *>: iterator ite = m_lst.end ();
For (; it! = Ite; it ++)
{
If (* It)-> m_id = ID)
Return (* It)-> pause ());
}
Return false;
}
Unsigned cmythreadpool: setsize (unsigned size)
{
Unsigned nowsize = m_lst.size ();
If (nowsize <= size)
{
Cmythread * PT;
Unsigned Inc = size-nowsize;
For (unsigned I = 0; I <Inc; I ++)
{
PT = new cmythread;
M_lst.push_back (PT );
}
Return size;
}
Else
{
Unsigned dec = nowsize-size;
List <cmythread *>: iterator it = m_lst.begin ();
List <cmythread *>: iterator ite = m_lst.end ();
List <cmythread *>: iterator itemp;
Unsigned I = 0;
For (; it! = Ite & I <Dec ;)
{
If (* It)-> m_status = threadpause)
{
Itemp = It ++;
Delete (* itemp ));
M_lst.erase (itemp );
I ++;
Continue;
}
It ++;
}
Sleep (100 * I );
Return m_lst.size ();
}
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.