home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 12.ddi / CLASSINC.PAK / THREAD.H < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  42.5 KB  |  831 lines

  1. /*------------------------------------------------------------------------*/
  2. /*                                                                        */
  3. /*  THREAD.H                                                              */
  4. /*                                                                        */
  5. /*  Copyright (c) 1993 Borland International                              */
  6. /*  All Rights Reserved                                                   */
  7. /*                                                                        */
  8. /*  Defines the class TCriticalSection and its nested class Lock.         */
  9. /*  Defines the class TMutex and its nested class Lock.                   */
  10. /*  Defines the class TSync and its nested class Lock.                    */
  11. /*  Defines the template TStaticSync and its nested class Lock.           */
  12. /*  Defines the class TThread.                                            */
  13. /*                                                                        */
  14. /*------------------------------------------------------------------------*/
  15.  
  16. #if !defined( __THREAD_H )
  17. #define __THREAD_H
  18.  
  19. #if !defined( __CSTRING_H )
  20. #include <cstring.h>
  21. #endif  // __CSTRING_H
  22.  
  23. #if !defined( __WINDOWS_H )
  24. #include <windows.h>
  25. #endif  // __WINDOWS_H
  26.  
  27. #if !defined( __CHECKS_H )
  28. #include <checks.h>
  29. #endif  // __CHECKS_H
  30.  
  31. #if !defined( __CLASSLIB_DEFS_H )
  32. #include "classlib\defs.h"
  33. #endif  // __CLASSLIB_DEFS_H
  34.  
  35. #if !defined(BI_MULTI_THREAD)
  36. #error Thread classes require multi-threaded operating system.
  37. #endif
  38.  
  39. #if defined( __OS2__ )
  40. #error Thread classes not implemented for OS/2.
  41. #endif
  42.  
  43. #if defined( BI_CLASSLIB_NO_po )
  44. #pragma option -po-
  45. #endif
  46.  
  47. /*------------------------------------------------------------------------*/
  48. /*                                                                        */
  49. /*  class TCriticalSection;                                               */
  50. /*  class TCriticalSection::Lock;                                         */
  51. /*                                                                        */
  52. /*  TCriticalSection provides a system-independent interface to critical  */
  53. /*  sections in threads. With suitable underlying implementations the     */
  54. /*  same code can be used under OS/2 and Windows NT.                      */
  55. /*                                                                        */
  56. /*  An object of type TCriticalSection can be used in conjunction with    */
  57. /*  objects of type TCriticalSection::Lock to guarantee that only one     */
  58. /*  thread can be executing any of the code sections protected by the     */
  59. /*  lock at any given time.                                               */
  60. /*                                                                        */
  61. /*  The differences between the classes TCriticalSection and TMutex are   */
  62. /*  that a timeout can be specified when creating a Lock on a TMutex      */
  63. /*  object, and that a TMutex object has a HANDLE which can be used       */
  64. /*  outside the class. This mirrors the distinction made in Windows NT    */
  65. /*  between a CRITICALSECTION and a Mutex. Under NT a TCriticalSection    */
  66. /*  object is much faster than a TMutex object. Under operating systems   */
  67. /*  that don't make this distinction a TCriticalSection object can use    */
  68. /*  the same underlying implementation as a TMutex, losing the speed      */
  69. /*  advantage that it has under NT.                                       */
  70. /*                                                                        */
  71. /*  TCriticalSection Public Interface                                     */
  72. /*  ---------------------------------                                     */
  73. /*                                                                        */
  74. /*      TCriticalSection();     Constructor. Takes no parameters.         */
  75. /*                                                                        */
  76. /*      ~TCriticalSection();    Destructor.                               */
  77. /*                                                                        */
  78. /*      class Lock;             Handles locking and unlocking of          */
  79. /*                              critical sections.                        */
  80. /*                                                                        */
  81. /*  TCriticalSection::Lock Public Interface                               */
  82. /*  ---------------------------------------                               */
  83. /*                                                                        */
  84. /*      Lock( const TCriticalSection& );                                  */
  85. /*                                                                        */
  86. /*                              Request a lock on the TCriticalSection    */
  87. /*                              object. If no Lock object in a different  */
  88. /*                              thread from the calling thread holds      */
  89. /*                              a lock on that object the lock is         */
  90. /*                              allowed and execution continues. If       */
  91. /*                              another thread holds a lock on that       */
  92. /*                              object the requesting thread is blocked   */
  93. /*                              until the owning thread has released all  */
  94. /*                              of its locks.                             */
  95. /*                                                                        */
  96. /*      ~Lock();                Releases the lock.                        */
  97. /*                                                                        */
  98. /*  Example                                                               */
  99. /*  -------                                                               */
  100. /*                                                                        */
  101. /*      TCriticalSection LockF;                                           */
  102. /*                                                                        */
  103. /*      void f()                                                          */
  104. /*      {                                                                 */
  105. /*      TCriticalSection::Lock lock(LockF);                               */
  106. /*      // critical processing goes here                                  */
  107. /*      }                                                                 */
  108. /*                                                                        */
  109. /*  Only one thread of execution will be allowed to execute the critical  */
  110. /*  code inside f() at any one time.                                      */
  111. /*                                                                        */
  112. /*------------------------------------------------------------------------*/
  113.  
  114. class TCriticalSection
  115. {
  116.  
  117. public:
  118.  
  119.     TCriticalSection();
  120.     ~TCriticalSection();
  121.  
  122.     class Lock
  123.     {
  124.     public:
  125.         Lock( const TCriticalSection& );
  126.         ~Lock();
  127.     private:
  128.         const TCriticalSection& CritSecObj;
  129.     };
  130.  
  131.     friend Lock;
  132.  
  133. private:
  134.  
  135.     CRITICAL_SECTION CritSec;
  136.  
  137.     TCriticalSection( const TCriticalSection& );
  138.     const TCriticalSection& operator = ( const TCriticalSection& );
  139.  
  140. };
  141.  
  142.  
  143. inline TCriticalSection::TCriticalSection()
  144. {
  145.     InitializeCriticalSection(CONST_CAST(CRITICAL_SECTION *,&CritSec));
  146. }
  147.  
  148. inline TCriticalSection::~TCriticalSection()
  149. {
  150.     DeleteCriticalSection(CONST_CAST(CRITICAL_SECTION *,&CritSec));
  151. }
  152.  
  153. inline TCriticalSection::Lock::Lock( const TCriticalSection& sec ) :
  154.     CritSecObj(sec)
  155. {
  156.     EnterCriticalSection(CONST_CAST(CRITICAL_SECTION *,&CritSecObj.CritSec));
  157. }
  158.  
  159. inline TCriticalSection::Lock::~Lock()
  160. {
  161.     LeaveCriticalSection(CONST_CAST(CRITICAL_SECTION *,&CritSecObj.CritSec));
  162. }
  163.  
  164. /*------------------------------------------------------------------------*/
  165. /*                                                                        */
  166. /*  class TMutex;                                                         */
  167. /*  class TMutex::Lock;                                                   */
  168. /*                                                                        */
  169. /*  TMutex provides a system-independent interface to critical            */
  170. /*  sections in threads. With suitable underlying implementations the     */
  171. /*  same code can be used under OS/2 and Windows NT.                      */
  172. /*                                                                        */
  173. /*  An object of type TMutex can be used in conjunction with              */
  174. /*  objects of type TMutex::Lock to guarantee that only one               */
  175. /*  thread can be executing any of the code sections protected by the     */
  176. /*  lock at any given time.                                               */
  177. /*                                                                        */
  178. /*  The differences between the classes TCriticalSection and TMutex are   */
  179. /*  that a timeout can be specified when creating a Lock on a TMutex      */
  180. /*  object, and that a TMutex object has a HANDLE which can be used       */
  181. /*  outside the class. This mirrors the distinction made in Windows NT    */
  182. /*  between a CRITICALSECTION and a Mutex. Under NT a TCriticalSection    */
  183. /*  object is much faster than a TMutex object. Under operating systems   */
  184. /*  that don't make this distinction a TCriticalSection object can use    */
  185. /*  the same underlying implementation as a TMutex, losing the speed      */
  186. /*  advantage that it has under NT.                                       */
  187. /*                                                                        */
  188. /*  TMutex Public Interface                                               */
  189. /*  ---------------------------------                                     */
  190. /*                                                                        */
  191. /*      TMutex();               Constructor. Takes no parameters.         */
  192. /*                                                                        */
  193. /*      ~TMutex();              Destructor.                               */
  194. /*                                                                        */
  195. /*      operator HANDLE() const;                                          */
  196. /*                              Returns a HANDLE to the TMutex object,    */
  197. /*                              for use in OS calls that require it.      */
  198. /*                                                                        */
  199. /*      class Lock;             Handles locking and unlocking of          */
  200. /*                              critical sections.                        */
  201. /*                                                                        */
  202. /*                                                                        */
  203. /*  TMutex::Lock Public Interface                                         */
  204. /*  ---------------------------------------                               */
  205. /*                                                                        */
  206. /*      Lock( const TMutex&,                                              */
  207. /*            unsigned long timeOut = NoLimit );                          */
  208. /*                                                                        */
  209. /*                              Request a lock on the TCriticalSection    */
  210. /*                              object. If no Lock object in a different  */
  211. /*                              thread from the calling thread holds      */
  212. /*                              a lock on that object the lock is         */
  213. /*                              allowed and execution continues. If       */
  214. /*                              another thread holds a lock on that       */
  215. /*                              object the requesting thread is blocked   */
  216. /*                              until the owning thread has released all  */
  217. /*                              of its locks.                             */
  218. /*                                                                        */
  219. /*      ~Lock();                Releases the lock.                        */
  220. /*                                                                        */
  221. /*  Example                                                               */
  222. /*  -------                                                               */
  223. /*                                                                        */
  224. /*      TMutex LockF;                                                     */
  225. /*                                                                        */
  226. /*      void f()                                                          */
  227. /*      {                                                                 */
  228. /*      TMutex::Lock lock(LockF);                                         */
  229. /*      // critical processing goes here                                  */
  230. /*      }                                                                 */
  231. /*                                                                        */
  232. /*  Only one thread of execution will be allowed to execute the critical  */
  233. /*  code inside f() at any one time.                                      */
  234. /*                                                                        */
  235. /*------------------------------------------------------------------------*/
  236.  
  237. class TMutex
  238. {
  239.  
  240. public:
  241.  
  242.     enum { NoLimit = -1 };  // Windows NT
  243.  
  244.     TMutex();
  245.     ~TMutex();
  246.  
  247.     operator HANDLE() const;
  248.  
  249.     class Lock
  250.     {
  251.     public:
  252.         Lock( const TMutex&, unsigned long timeOut = NoLimit );
  253.         ~Lock();
  254.  
  255.         void Release();
  256.  
  257.     private:
  258.         const TMutex& MutexObj;
  259.  
  260.     };
  261.  
  262.     friend Lock;
  263.  
  264. private:
  265.  
  266.     HANDLE Handle;
  267.  
  268.     TMutex( const TMutex& );
  269.     const TMutex& operator = ( const TMutex& );
  270.  
  271. };
  272.  
  273.  
  274. inline TMutex::TMutex()
  275. {
  276.     Handle = ::CreateMutex( 0, FALSE, 0 );
  277. }
  278.  
  279. inline TMutex::~TMutex()
  280. {
  281.     ::CloseHandle(Handle);
  282. }
  283.  
  284. inline TMutex::operator HANDLE() const
  285. {
  286.     return Handle;
  287. }
  288.  
  289. inline TMutex::Lock::Lock( const TMutex& mutex, unsigned long timeOut ) :
  290.     MutexObj(mutex)
  291. {
  292.     ::WaitForSingleObject( MutexObj, timeOut );
  293. }
  294.  
  295. inline TMutex::Lock::~Lock()
  296. {
  297.     Release();
  298. }
  299.  
  300. inline void TMutex::Lock::Release()
  301. {
  302.     ::ReleaseMutex(MutexObj);
  303. }
  304.  
  305. /*------------------------------------------------------------------------*/
  306. /*                                                                        */
  307. /*  class TSync;                                                          */
  308. /*  class TSync::Lock;                                                    */
  309. /*                                                                        */
  310. /*  TSync provides a system-independent interface to build classes        */
  311. /*  that act like monitors, i.e., classes in which only one member        */
  312. /*  can execute on a particular instance at any one time. TSync uses      */
  313. /*  TCriticalSection, so it is portable to all platforms that             */
  314. /*  TCriticalSection has been ported to.                                  */
  315. /*                                                                        */
  316. /*  TSync Public Interface                                                */
  317. /*  -------------------------                                             */
  318. /*                                                                        */
  319. /*  None. TSync can only be a base class.                                 */
  320. /*                                                                        */
  321. /*  TSync Protected Interface                                             */
  322. /*  ----------------------------                                          */
  323. /*                                                                        */
  324. /*      TSync( const TSync& );                                            */
  325. /*                              Copy constructor. Does not copy the       */
  326. /*                              TCriticalSection object.                  */
  327. /*                                                                        */
  328. /*      const TSync& operator = ( const TSync& );                         */
  329. /*                              Assignment operator. Does not copy the    */
  330. /*                              TCriticalSection object.                  */
  331. /*                                                                        */
  332. /*      class Lock;             Handles locking and unlocking of member   */
  333. /*                              functions.                                */
  334. /*                                                                        */
  335. /*  Example                                                               */
  336. /*  -------                                                               */
  337. /*                                                                        */
  338. /*                                                                        */
  339. /*      class ThreadSafe : private TSync                                  */
  340. /*      {                                                                 */
  341. /*      public:                                                           */
  342. /*          void f();                                                     */
  343. /*          void g();                                                     */
  344. /*      private:                                                          */
  345. /*          int i;                                                        */
  346. /*      };                                                                */
  347. /*                                                                        */
  348. /*      void ThreadSafe::f()                                              */
  349. /*      {                                                                 */
  350. /*      Lock(this);                                                       */
  351. /*      if( i == 2 )                                                      */
  352. /*          i = 3;                                                        */
  353. /*      }                                                                 */
  354. /*                                                                        */
  355. /*      void ThreadSafe::g()                                              */
  356. /*      {                                                                 */
  357. /*      Lock(this);                                                       */
  358. /*      if( i == 3 )                                                      */
  359. /*          i = 2;                                                        */
  360. /*      }                                                                 */
  361. /*                                                                        */
  362. /*------------------------------------------------------------------------*/
  363.  
  364. class TSync
  365. {
  366.  
  367. protected:
  368.  
  369.     TSync();
  370.     TSync( const TSync& );
  371.     const TSync& operator = ( const TSync& );
  372.  
  373.     class Lock : private TCriticalSection::Lock
  374.     {
  375.     public:
  376.         Lock( const TSync * );
  377.     private:
  378.         static const TCriticalSection& GetRef( const TSync * );
  379.     };
  380.  
  381.     friend Lock;
  382.  
  383. private:
  384.  
  385.     TCriticalSection CritSec;
  386.  
  387. };
  388.  
  389. inline TSync::TSync()
  390. {
  391. }
  392.  
  393. inline TSync::TSync( const TSync& )
  394. {
  395. }
  396.  
  397. inline const TSync& TSync::operator = ( const TSync& )
  398. {
  399.     return *this;
  400. }
  401.  
  402. inline TSync::Lock::Lock( const TSync *sync ) :
  403.     TCriticalSection::Lock(GetRef(sync))
  404. {
  405. }
  406.  
  407. inline const TCriticalSection& TSync::Lock::GetRef( const TSync *sync )
  408. {
  409.     CHECK( sync != 0 );
  410.     return sync->CritSec;
  411. }
  412.  
  413. /*------------------------------------------------------------------------*/
  414. /*                                                                        */
  415. /*  template <class T> class TStaticSync;                                 */
  416. /*  template <class T> class TStaticSync::Lock;                           */
  417. /*                                                                        */
  418. /*  TStaticSync provides a system-independent interface to build sets     */
  419. /*  of classes that act somewhat like monitors, i.e., classes in which    */
  420. /*  only one member function can execute at any one time regardless of    */
  421. /*  which instance it is being called on. TStaticSync uses                */
  422. /*  TCriticalSection, so it is portable to all platforms that             */
  423. /*  TCriticalSection has been ported to.                                  */
  424. /*                                                                        */
  425. /*  TStaticSync Public Interface                                          */
  426. /*  -------------------------                                             */
  427. /*                                                                        */
  428. /*  None. TStaticSync can only be a base class.                           */
  429. /*                                                                        */
  430. /*  TStaticSync Protected Interface                                       */
  431. /*  ----------------------------                                          */
  432. /*                                                                        */
  433. /*      TStaticSync<T>( const TStaticSync<T>& );                          */
  434. /*                              Copy constructor. Does not copy the       */
  435. /*                              TCriticalSection object.                  */
  436. /*                                                                        */
  437. /*      const TStaticSync<T>& operator = ( const TStaticSync<T>& );       */
  438. /*                              Assignment operator. Does not copy the    */
  439. /*                              TCriticalSection object.                  */
  440. /*                                                                        */
  441. /*      class Lock;             Handles locking and unlocking of member   */
  442. /*                              functions.                                */
  443. /*                                                                        */
  444. /*  Example                                                               */
  445. /*  -------                                                               */
  446. /*                                                                        */
  447. /*                                                                        */
  448. /*      class ThreadSafe : private TStaticSync<ThreadSafe>                */
  449. /*      {                                                                 */
  450. /*      public:                                                           */
  451. /*          void f();                                                     */
  452. /*          void g();                                                     */
  453. /*      private:                                                          */
  454. /*          static int i;                                                 */
  455. /*      };                                                                */
  456. /*                                                                        */
  457. /*      void ThreadSafe::f()                                              */
  458. /*      {                                                                 */
  459. /*      Lock(this);                                                       */
  460. /*      if( i == 2 )                                                      */
  461. /*          i = 3;                                                        */
  462. /*      }                                                                 */
  463. /*                                                                        */
  464. /*      void ThreadSafe::g()                                              */
  465. /*      {                                                                 */
  466. /*      Lock(this);                                                       */
  467. /*      if( i == 3 )                                                      */
  468. /*          i = 2;                                                        */
  469. /*      }                                                                 */
  470. /*                                                                        */
  471. /*------------------------------------------------------------------------*/
  472.  
  473. template <class T> class TStaticSync
  474. {
  475.  
  476. protected:
  477.  
  478.     TStaticSync();
  479.     ~TStaticSync();
  480.     TStaticSync( const TStaticSync<T>& );
  481.     const TStaticSync<T>& operator = ( const TStaticSync<T>& );
  482.  
  483.     class Lock : private TCriticalSection::Lock
  484.     {
  485.     public:
  486.         Lock() : TCriticalSection::Lock(*TStaticSync<T>::CritSec) {}
  487.     };
  488.  
  489.     friend Lock;
  490.  
  491. private:
  492.  
  493.     static TCriticalSection *CritSec;
  494.     static unsigned long Count;
  495.  
  496. };
  497.  
  498. template <class T> TCriticalSection *TStaticSync<T>::CritSec;
  499. template <class T> unsigned long TStaticSync<T>::Count;
  500.  
  501. template <class T> inline TStaticSync<T>::TStaticSync()
  502. {
  503.     if( Count++ == 0 )
  504.         CritSec = new TCriticalSection;
  505. }
  506.  
  507. template <class T> inline TStaticSync<T>::~TStaticSync()
  508. {
  509.     if( --Count == 0 )
  510.         delete CritSec;
  511. }
  512.  
  513. template <class T>
  514. inline TStaticSync<T>::TStaticSync( const TStaticSync<T>& )
  515. {
  516. }
  517.  
  518. template <class T>
  519. inline const TStaticSync<T>& TStaticSync<T>::operator = ( const TStaticSync<T>& )
  520. {
  521.     return *this;
  522. }
  523.  
  524. #if 0
  525. template <class T>
  526. inline TStaticSync::Lock::Lock() :
  527.     TCriticalSection::Lock(TStaticSync<T>::CritSec)
  528. {
  529. }
  530. #endif
  531.  
  532. /*------------------------------------------------------------------------*/
  533. /*                                                                        */
  534. /*  class TThread;                                                        */
  535. /*                                                                        */
  536. /*  TThread provides a system-independent interface to threads. With      */
  537. /*  suitable underlying implementations the same code can be used under   */
  538. /*  OS/2 and Windows NT.                                                  */
  539. /*                                                                        */
  540. /*  TThread Public Interface                                              */
  541. /*  ------------------------                                              */
  542. /*                                                                        */
  543. /*      Start();                Begins execution of the thread. Returns   */
  544. /*                              the handle of the thread.                 */
  545. /*                                                                        */
  546. /*      Suspend();              Suspends execution of the thread.         */
  547. /*      Resume();               Resumes execution of a suspended thread.  */
  548. /*                                                                        */
  549. /*      Terminate();            Sets an internal flag that indicates      */
  550. /*                              that the thread should exit. The          */
  551. /*                              derived class can check the state of      */
  552. /*                              this flag by calling ShouldTerminate().   */
  553. /*                                                                        */
  554. /*      WaitForExit( unsigned long timeout = (unsigned long)(-1) );       */
  555. /*                              Blocks the calling thread until the       */
  556. /*                              internal thread exits or until the time   */
  557. /*                              specified by timeout, in milliseconds,    */
  558. /*                              expires. A timeout of -1 says to wait     */
  559. /*                              indefinitely.                             */
  560. /*                                                                        */
  561. /*      TerminateAndWait( unsigned long timeout = (unsigned long)(-1) );  */
  562. /*                              Combines the behavior of Terminate() and  */
  563. /*                              WaitForExit(). Sets an internal flag that */
  564. /*                              indicates that the thread should exit     */
  565. /*                              and blocks the calling thread until the   */
  566. /*                              internal thread exits or until the time   */
  567. /*                              specified by timeout, in milliseconds,    */
  568. /*                              expires. A timeout of -1 says to wait     */
  569. /*                              indefinitely.                             */
  570. /*                                                                        */
  571. /*      GetStatus();            Gets the current status of the thread.    */
  572. /*                              See TThread::Status for possible values.  */
  573. /*                                                                        */
  574. /*      GetPriority();          Gets the priority of the thread.          */
  575. /*      SetPriority();          Sets the priority of the thread.          */
  576. /*                                                                        */
  577. /*      enum Status;            Identifies the states that the class      */
  578. /*                              can be in.                                */
  579. /*                                                                        */
  580. /*          Created             The class has been created but the        */
  581. /*                              thread has not been started.              */
  582. /*          Running             The thread is running.                    */
  583. /*                                                                        */
  584. /*          Suspended           The thread has been suspended.            */
  585. /*                                                                        */
  586. /*          Finished            The thread has finished execution.        */
  587. /*                                                                        */
  588. /*          Invalid             The object is invalid. Currently this     */
  589. /*                              happens only when the operating system    */
  590. /*                              is unable to start the thread.            */
  591. /*                                                                        */
  592. /*      class ThreadError;      The error class that defines the objects  */
  593. /*                              that are thrown when an error occurs.     */
  594. /*                                                                        */
  595. /*  TThread::ThreadError Public Interface                                 */
  596. /*  -------------------------------------                                 */
  597. /*                                                                        */
  598. /*      enum ErrorType;         Identifies the type of error that         */
  599. /*                              occurred.                                 */
  600. /*                                                                        */
  601. /*          SuspendBeforeRun    The user called Suspend() on an object    */
  602. /*                              before calling Start().                   */
  603. /*                                                                        */
  604. /*          ResumeBeforeRun     The user called Resume() on an object     */
  605. /*                              before calling Start().                   */
  606. /*                                                                        */
  607. /*          ResumeDuringRun     The user called Resume() on a thread that */
  608. /*                              was not Suspended.                        */
  609. /*                                                                        */
  610. /*          SuspendAfterExit    The user called Suspend() on an object    */
  611. /*                              whose thread had already exited.          */
  612. /*                                                                        */
  613. /*          ResumeAfterExit     The user called Resume() on an object     */
  614. /*                              whose thread had already exited.          */
  615. /*                                                                        */
  616. /*          CreationFailure     The operating system was unable to create */
  617. /*                              the thread.                               */
  618. /*                                                                        */
  619. /*          DestroyBeforeExit   The object's destructor was invoked       */
  620. /*                              its thread had exited.                    */
  621. /*                                                                        */
  622. /*          AssignError         An attempt was made to assign to an       */
  623. /*                              object that was not in either the         */
  624. /*                              Created or the Finished state.            */
  625. /*                                                                        */
  626. /*      ErrorType GetErrorType() const;                                   */
  627. /*                              Returns a code indicating the type of     */
  628. /*                              error that occurred.                      */
  629. /*                                                                        */
  630. /*      string why();           Returns a string that describes the       */
  631. /*                              error. Inherited from xmsg.               */
  632. /*                                                                        */
  633. /*  TThread Protected Interface                                           */
  634. /*  ---------------------------                                           */
  635. /*                                                                        */
  636. /*      TThread();              Creates an object of type TThread.        */
  637. /*      virtual ~TThread();     Destroys the object.                      */
  638. /*                                                                        */
  639. /*      const TThread& operator = ( const TThread& );                     */
  640. /*                              The target object must be in either the   */
  641. /*                              Created state or the Finished state. If   */
  642. /*                              so, puts the object into the Created      */
  643. /*                              state. If the object is not in either the */
  644. /*                              Created state or the Finished state it    */
  645. /*                              is an error and an exception will be      */
  646. /*                              thrown.                                   */
  647. /*                                                                        */
  648. /*      TThread( const TThread& );                                        */
  649. /*                              Pts the object into the Created           */
  650. /*                              state, just like the default constructor. */
  651. /*                              Does not copy any of the internal details */
  652. /*                              of the thread being copied.               */
  653. /*                                                                        */
  654. /*      virtual unsigned long Run() = 0;                                  */
  655. /*                              The function that does the work. Calling  */
  656. /*                              Start() creates a thread that begins      */
  657. /*                              executing Run() with the 'this' pointer   */
  658. /*                              pointing to the TThread-based object.     */
  659. /*                                                                        */
  660. /*      int ShouldTerminate() const;                                      */
  661. /*                              Returns a non-zero value to indicate      */
  662. /*                              that Terminate() or TerminateAndWait()    */
  663. /*                              has been called. If this capability is    */
  664. /*                              being used, the thread should call        */
  665. /*                              ShouldTerminate() regularly, and if it    */
  666. /*                              returns a non-zero value the thread       */
  667. /*                              finish its processing and exit.           */
  668. /*                                                                        */
  669. /*  Example                                                               */
  670. /*  -------                                                               */
  671. /*                                                                        */
  672. /*      class TimerThread : public TThread                                */
  673. /*      {                                                                 */
  674. /*      public:                                                           */
  675. /*          TimerThread() : Count(0) {}                                   */
  676. /*      private:                                                          */
  677. /*          unsigned long Run();                                          */
  678. /*          int Count;                                                    */
  679. /*      };                                                                */
  680. /*                                                                        */
  681. /*      unsigned long TimerThread::Run()                                  */
  682. /*      {                                                                 */
  683. /*      // loop 10 times                                                  */
  684. /*      while( Count++ < 10 )                                             */
  685. /*          {                                                             */
  686. /*          Sleep(1000);    // delay 1 second                             */
  687. /*          cout << "Iteration " << Count << endl;                        */
  688. /*          }                                                             */
  689. /*      return 0L;                                                        */
  690. /*      }                                                                 */
  691. /*                                                                        */
  692. /*      int main()                                                        */
  693. /*      {                                                                 */
  694. /*      TimerThread timer;                                                */
  695. /*      timer.Start();                                                    */
  696. /*      Sleep( 20000 );     // delay 20 seconds                           */
  697. /*      return 0;                                                         */
  698. /*      }                                                                 */
  699. /*                                                                        */
  700. /*  Internal States                                                       */
  701. /*  ---------------                                                       */
  702. /*                                                                        */
  703. /*  Created :   the object has been created but its thread has not been   */
  704. /*              started. The only valid transition from this state is     */
  705. /*              to Running, which happens on a call to Start(). In        */
  706. /*              particular, a call to Suspend() or Resume() when the      */
  707. /*              object is in this state is an error and will throw an     */
  708. /*              exception.                                                */
  709. /*                                                                        */
  710. /*  Running:    the thread has been started successfully. There are two   */
  711. /*              transitions from this state:                              */
  712. /*                                                                        */
  713. /*                  When the user calls Suspend() the object moves into   */
  714. /*                  the Suspended state.                                  */
  715. /*                                                                        */
  716. /*                  When the thread exits the object moves into the       */
  717. /*                  Finished state.                                       */
  718. /*                                                                        */
  719. /*              Calling Resume() on an object that is in the Running      */
  720. /*              state is an error and will throw an exception.            */
  721. /*                                                                        */
  722. /*  Suspended:  the thread has been suspended by the user. Subsequent     */
  723. /*              calls to Suspend() nest, so there must be as many calls   */
  724. /*              to Resume() as there were to Suspend() before the thread  */
  725. /*              actually resumes execution.                               */
  726. /*                                                                        */
  727. /*  Finished:   the thread has finished executing. There are no valid     */
  728. /*              transitions out of this state. This is the only state     */
  729. /*              from which it is legal to invoke the destructor for the   */
  730. /*              object. Invoking the destructor when the object is in     */
  731. /*              any other state is an error and will throw an exception.  */
  732. /*                                                                        */
  733. /*------------------------------------------------------------------------*/
  734.  
  735. class _BIDSCLASS TThread
  736. {
  737.  
  738. public:
  739.  
  740.     enum Status { Created, Running, Suspended, Finished, Invalid };
  741.     enum { NoLimit = -1 };      // Windows NT
  742.  
  743.     HANDLE Start();
  744.     unsigned long Suspend();
  745.     unsigned long Resume();
  746.     void Terminate();
  747.     unsigned long WaitForExit( unsigned long timeout = NoLimit );
  748.     unsigned long TerminateAndWait( unsigned long timeout = NoLimit );
  749.  
  750.     Status GetStatus() const;
  751.  
  752.     int GetPriority() const;
  753.     int SetPriority(int);
  754.  
  755.     class ThreadError : public xmsg
  756.         {
  757.         friend TThread;
  758.         public:
  759.             enum ErrorType
  760.                 {
  761.                 SuspendBeforeRun,
  762.                 ResumeBeforeRun,
  763.                 ResumeDuringRun,
  764.                 SuspendAfterExit,
  765.                 ResumeAfterExit,
  766.                 CreationFailure,
  767.                 DestroyBeforeExit,
  768.                 AssignError
  769.                 };
  770.             ErrorType GetErrorType() const;
  771.         private:
  772.             ThreadError(ErrorType type);
  773.             static string MakeString(ErrorType type );
  774.             ErrorType Type;
  775.         };
  776.  
  777. protected:
  778.  
  779.     TThread();
  780.     virtual ~TThread();
  781.  
  782.     // Copying a thread puts the target into the Created state
  783.     const TThread& operator = ( const TThread& );
  784.     TThread( const TThread& );
  785.  
  786.     int ShouldTerminate() const;
  787.  
  788. private:
  789.  
  790.     virtual unsigned long Run() = 0;
  791.     static unsigned long _stdcall Execute( void *thread );
  792.  
  793.     Status CheckStatus() const;
  794.  
  795.     HANDLE Handle;
  796.     DWORD ThreadId;
  797.     Status Stat;
  798.  
  799.     int TerminationRequested;
  800.  
  801. };
  802.  
  803. inline TThread::Status TThread::GetStatus() const
  804. {
  805.     if( Stat == Running )
  806.         CONST_CAST(TThread *,this)->Stat = CheckStatus();
  807.     return Stat;
  808. }
  809.  
  810. inline int TThread::GetPriority() const
  811. {
  812.     return ::GetThreadPriority(Handle);
  813. }
  814.  
  815. inline int TThread::ShouldTerminate() const
  816. {
  817.     return TerminationRequested;
  818. }
  819.  
  820. inline TThread::ThreadError::ErrorType TThread::ThreadError::GetErrorType() const
  821. {
  822.     return Type;
  823. }
  824.  
  825. #if defined( BI_CLASSLIB_NO_po )
  826. #pragma option -po.
  827. #endif
  828.  
  829. #endif  // __THREAD_H
  830.  
  831.