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 ();
}
}