home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / deans.zip / PROCESS.HPP < prev    next >
C/C++ Source or Header  |  1994-09-14  |  20KB  |  503 lines

  1. //
  2. // NAME: CIDLib_Process.Hpp
  3. //
  4. // DESCRIPTION:
  5. //
  6. //  This module provides task and thread control classes. Threads are named
  7. //  for easy identification in log file messages and such. The
  8. //  CIDLib_Process.Cpp module maintains a linked list of threads that a
  9. //  process starts so that it can insure that thread names are not
  10. //  duplicated.
  11. //
  12. //  The relevant portion of the hierarchy is:
  13. //
  14. //              CIDOBJECT
  15. //                  │
  16. //               THREAD
  17. //
  18. //
  19. //
  20. // AUTHOR: Dean Roddey
  21. //
  22. // CREATE DATE: 04/16/93
  23. //
  24. // COPYRIGHT: 1992..1994, 'CIDCorp
  25. //
  26. // CAVEATS/GOTCHAS:
  27. //
  28. //  1)  When a thread object is created, a function address is passed to it
  29. //      that will become the thread entry point. That function must be a
  30. //      pfnTHREADFUNC function.
  31. //
  32. //  2)  The destructor for a thread object can be called while the thread is
  33. //      still running. It will kill the thread if so.
  34. //
  35. //  3)  A simple synchonization method is provided via the WaitSync()/Sync()
  36. //      methods, which allow two threads to sync up with each other. If the
  37. //      controlling application needs more complex synchronization, it must
  38. //      communicate with the thread via some IPC mechanism.
  39. //
  40. //  4)  Other subsystems can register to have an object created for every
  41. //      thread that is constructed. This gives them the ability to have
  42. //      per-thread data with no effort.
  43. //
  44. //  5)  Each thread object has a CIDERROR object into which the last error
  45. //      that occured on that thread can be stored. The client can query this
  46. //      last error, which will clear it.
  47. //
  48. //  6)  An exception handler is installed for every thread. If will clear the
  49. //      thread's state flags when it is killed and will log exception info
  50. //      when the thread has an access violation that is not handled by a
  51. //      higher level exception handler.
  52. //
  53. //
  54. // MODIFICATION LOG:
  55. //
  56.  
  57.  
  58. // Avoid multiple inclusion
  59. #if        !defined(CIDLIB_PROCESS_HPP)
  60. #define    CIDLIB_PROCESS_HPP
  61.  
  62.  
  63. // -----------------------------------------------------------------------------
  64. //  Forward reference some structures needed for a friend declaration below
  65. // -----------------------------------------------------------------------------
  66. struct  _EXCEPTIONREPORTRECORD;
  67. struct  _EXCEPTIONREGISTRATIONRECORD;
  68. struct  _CONTEXT;
  69.  
  70.  
  71.  
  72. // -----------------------------------------------------------------------------
  73. //  Process related constants
  74. // -----------------------------------------------------------------------------
  75. const tCIDLib::CARD4 c4MaxPTObjs        = 64;
  76.  
  77.  
  78.  
  79. // -----------------------------------------------------------------------------
  80. //   CLASS: THREAD
  81. //  PREFIX: thr
  82. //
  83. //  This class provides thread support.
  84. // -----------------------------------------------------------------------------
  85. class               THREAD : public CIDOBJECT
  86. {
  87.     public          :
  88.         // ---------------------------------------------------------------------
  89.         //  Contructors and Destructors
  90.         //
  91.         //  THREAD
  92.         //      This is the only contructor for threads. The default
  93.         //      constructor is protected so that it can't be called by
  94.         //      accident, it is also not exported. The bAutoStart flag
  95.         //      indicates whether the thread should be started during the
  96.         //      constructor or just instantiated in a dormant state, to be
  97.         //      stated by a call to c4Start() call. It defaults to FALSE,
  98.         //      which means no autostart. The bSelfPrio parm indicates
  99.         //      whether this thread should not allow any other thread to
  100.         //      set his priority.
  101.         //
  102.         //  ~THREAD
  103.         //      This is the destructor for threads. It will remove the
  104.         //      thread object from the list of thread objects maintained by
  105.         //      CIDLib_Process.Cpp. This guy will destroy the __perrLast
  106.         //      object and the thread data  buffer that was passed to the
  107.         //      thread.
  108.         // ---------------------------------------------------------------------
  109.         THREAD
  110.         (
  111.             const   STRG32&                 strName
  112.             ,       tCIDLib::pfnTHREADFUNC  pbFunc
  113.             ,       tCIDLib::CARD4          c4StackSz = 0x7FFF
  114.             ,       tCIDLib::VOID*          pData = 0
  115.             ,       tCIDLib::eBOOL          bAutoStart = tCIDLib::eFALSE
  116.             ,       tCIDLib::eBOOL          bSelfPrio = tCIDLib::eFALSE
  117.         );
  118.  
  119.         ~THREAD();
  120.  
  121.  
  122.  
  123.         // ---------------------------------------------------------------------
  124.         //  Static methods
  125.         //
  126.         //  c4RegisterPerThreadObj
  127.         //      This method can be called by subsystems to register per-thread
  128.         //      object storage. For every thread created, each subsystem's
  129.         //      callout function (the pfnPerThread parm) is called to allow
  130.         //      them to create an object for that thread. The return is a handle
  131.         //      that the subsystem can use to access the object later. The
  132.         //      passed object name string is just a descriptive string used for
  133.         //      logging messages regarding this object.
  134.         //      This is not exported directly to the user, they have an API via
  135.         //      the facCIDLib facility to register per-thread objects.
  136.         // ---------------------------------------------------------------------
  137.         static tCIDLib::CARD4 c4RegisterPerThreadObj
  138.         (
  139.             const   STRG64&                 strObjName
  140.             ,       tCIDLib::pfnPTHRFUNC    pfnPerThread
  141.         );
  142.  
  143.         // ---------------------------------------------------------------------
  144.         //  Public, inherited methods
  145.         //
  146.         //  FormatToStr
  147.         //      Formats some debug info into the string.
  148.         // ---------------------------------------------------------------------
  149.         STDVPUBMETHODS(THREAD,CIDOBJECT,tCIDLib::eFALSE);
  150.  
  151.         virtual tCIDLib::VOID FormatToStr
  152.         (
  153.                     STRGBUF&                strbDest
  154.         ) const;
  155.  
  156.  
  157.         // ---------------------------------------------------------------------
  158.         //  Public virtual methods
  159.         //
  160.         //  Init
  161.         //  Terminate
  162.         //      These methods are used to give derived classes a chance to get
  163.         //      control after the thread is created but before the client's
  164.         //      thread function is called and after the client's thread
  165.         //      returns, but before the thread is terminated. But, if the
  166.         //      autostart is used to start the thread from the THREAD
  167.         //      constructor, the derived class's constructor will not have
  168.         //      been entered at the time of the Init call.
  169.         // ---------------------------------------------------------------------
  170.         virtual tCIDLib::VOID Init() {}
  171.  
  172.         virtual tCIDLib::VOID Terminate() {}
  173.  
  174.  
  175.         // ---------------------------------------------------------------------
  176.         //  Public, non-virtual methods
  177.         //
  178.         //  bIsRunning
  179.         //      The method will return the running flag
  180.         //
  181.         //  bProbeBuffer
  182.         //      This method will install an exception handler and then probe
  183.         //      the bounds of the passed buffer. If the probe generates an
  184.         //      exception, the return is eFALSE. It just reads the first and
  185.         //      last byte of the buffer, not the whole thing.
  186.         //
  187.         //  bRelease
  188.         //      When another thread has synced with this thread, this thread
  189.         //      will be blocked until the other thread calls this thread's
  190.         //      bRelease() to let this thread go again.
  191.         //
  192.         //  bStart
  193.         //      This method will start the thread running if not already.
  194.         //
  195.         //  bWaitSync
  196.         //      This method is called by another thread to sync up with this
  197.         //      thread. The other thread will be blocked until this thread
  198.         //      calls bSync(), at which time the other thead will unblock.
  199.         //
  200.         //  ClrLastErr
  201.         //      This guy will clear the error info for the thread. It is
  202.         //      inline for speed.
  203.         //
  204.         //  c4LastErrCode
  205.         //      Returns the error code of the last error stored away by this
  206.         //      thread. This will clear the error.
  207.         //
  208.         //  pfnSetOnExit
  209.         //      This will set a new On-Exit function for this thread and
  210.         //      return the current one. It can only be called by this thread.
  211.         //
  212.         //  perrLast
  213.         //      Returns a pointer to the last error object. This will clear
  214.         //      the last error and the caller is responsible for deleting
  215.         //      the object.
  216.         //
  217.         //  SetPriority
  218.         //      This method will set the priority of this thread. If the
  219.         //      thread is in 'self prio' mode, no other thread can call this
  220.         //      method. One verion allows a set of the class and absolute
  221.         //      level with that class (which must be less than the value
  222.         //      tCIDLib::c4MaxPrioLev.) The other version just sets the
  223.         //      relative level with the existing class, so it takes a signed
  224.         //      offset from the current value.
  225.         //
  226.         //  StoreNewError
  227.         //      Stores a new last error for this thread. It deletes the last
  228.         //      stored error and saves away the address of the new one. Only
  229.         //      this thread can call it.
  230.         //
  231.         //  strName
  232.         //      Returns a cosnstant reference to the name of the thread
  233.         //
  234.         //  Sync
  235.         //      This method can be called by the thread function to sync up
  236.         //      with another thread. If another thread has called bWaitSync()
  237.         //      and is waiting for this thread to sync, then this thread will
  238.         //      block and the other will be awakened. The other thread can do
  239.         //      whatever is needed. The other thead can then call bRelease()
  240.         //      to let this thread go again. Only this thread can call this
  241.         //      method.
  242.         //
  243.         //  tidThread
  244.         //      Returns the thread id. Should not be needed by public but just
  245.         //      in case.
  246.         // ---------------------------------------------------------------------
  247.         tCIDLib::eBOOL bIsRunning
  248.         (
  249.         )   const   {return __bRunning;}
  250.  
  251.         tCIDLib::eBOOL bProbeBuffer
  252.         (
  253.                     tCIDLib::VOID*          pBuffer
  254.             ,       tCIDLib::CARD4          c4Len
  255.         );
  256.  
  257.         tCIDLib::eBOOL bRelease();
  258.  
  259.         tCIDLib::eBOOL bStart();
  260.  
  261.         tCIDLib::eBOOL bWaitSync();
  262.  
  263.         tCIDLib::VOID ClrLastErr();
  264.  
  265.         tCIDLib::CARD4 c4LastErrCode();
  266.  
  267.         tCIDLib::VOID GetPriority
  268.         (
  269.                     tCIDLib::ePRTYCLASS&    ePrtyClass
  270.             ,       tCIDLib::CARD4&         c4PrioLev
  271.         );
  272.  
  273.         tCIDLib::pfnEXITFUNC pfnSetOnExit
  274.         (
  275.                     tCIDLib::pfnEXITFUNC    pfnNew
  276.         );
  277.  
  278.         CIDERROR* perrLast();
  279.  
  280.         tCIDLib::VOID SetPriority
  281.         (
  282.                     tCIDLib::ePRTYCLASS     ePrtyClass
  283.             ,       tCIDLib::CARD4          c4PrioLev
  284.         );
  285.  
  286.         tCIDLib::VOID SetPriority
  287.         (
  288.                     tCIDLib::INT4           i4PrioLev
  289.         );
  290.  
  291.         tCIDLib::VOID StoreNewError
  292.         (
  293.                     CIDERROR*               perrNew
  294.         );
  295.  
  296.         const STRG32& strName() const;
  297.  
  298.         tCIDLib::VOID Sync();
  299.  
  300.         TID tidThread
  301.         (
  302.         )   const   {return __tidThread;}
  303.  
  304.  
  305.  
  306.     protected       :
  307.         // ---------------------------------------------------------------------
  308.         //  Hidden constructors/operators
  309.         //
  310.         //  THREAD
  311.         //      Hide the default constructor so that empty threads can't be
  312.         //      created. Hide the copy constructor and assignment operator
  313.         //      so they can't be assigned.
  314.         // ---------------------------------------------------------------------
  315.         THREAD();
  316.  
  317.         THREAD
  318.         (
  319.             const   THREAD&                 thrSrc
  320.         );
  321.  
  322.         THREAD& operator=
  323.         (
  324.             const   THREAD&                 thrSrc
  325.         );
  326.  
  327.         // ---------------------------------------------------------------------
  328.         //  Protected, inherited methods
  329.         //
  330.         //  _bIsEqual
  331.         //      This method is called from the public bIsEqual, which has
  332.         //      determined that the objects are of comparable classes and are
  333.         //      not the same object. It does the comparison down the class
  334.         //      hierarchy.
  335.         // ---------------------------------------------------------------------
  336.         virtual tCIDLib::eBOOL _bIsEqual
  337.         (
  338.             const   CIDOBJECT&              objTarget
  339.         )   const;
  340.  
  341.  
  342.         // ---------------------------------------------------------------------
  343.         //  Protected, non-virtual methods
  344.         //
  345.         //  _CheckIsCallerSelf
  346.         //      This method will make sure that the calling thread is this
  347.         //      thread. If not, it will issue a fatal error message using the
  348.         //      passed method name. An optional text message can be passed
  349.         //      that will be placed into the aux text of the logged error.
  350.         //
  351.         //  _Exiting
  352.         //      This is provided so that the thread exception handler
  353.         //      installed for every thread can clear the running flag.
  354.         // ---------------------------------------------------------------------
  355.         tCIDLib::VOID _CheckCallerIsSelf
  356.         (
  357.             const   tCIDLib::CH*            pszMethod
  358.             , const tCIDLib::CH*            pszAuxText = 0
  359.         )   const;
  360.  
  361.         tCIDLib::VOID _Exiting();
  362.  
  363.  
  364.         // ---------------------------------------------------------------------
  365.         //  Declare friends
  366.         // ---------------------------------------------------------------------
  367.         friend tCIDLib::eBOOL _bInitProcess();
  368.  
  369.         friend APIRET APIENTRY __ThreadException
  370.         (
  371.             _EXCEPTIONREPORTRECORD*         pRep
  372.             , _EXCEPTIONREGISTRATIONRECORD* pReg
  373.             , _CONTEXT*                     pContext
  374.             , tCIDLib::VOID*                pDummy
  375.         );
  376.  
  377.         friend tCIDLib::VOID THREADFUNC __ThreadStart
  378.         (
  379.                     tCIDLib::VOID*          pData
  380.         );
  381.  
  382.         friend tCIDLib::VOID _LogExceptInfo
  383.         (
  384.             _EXCEPTIONREPORTRECORD*         pRep
  385.             , _EXCEPTIONREGISTRATIONRECORD* pReg
  386.             , _CONTEXT*                     pContext
  387.         );
  388.  
  389.  
  390.     private         :
  391.         // ---------------------------------------------------------------------
  392.         //  Private, non-virtual methods
  393.         //
  394.         //  __CreatePerThreadObjs
  395.         //      This method will create any registered per-thread objects for
  396.         //      this thread.
  397.         //
  398.         //  __DestroyPerThreadObjs
  399.         //      This method will destroy the object's per thead objects.
  400.         // ---------------------------------------------------------------------
  401.         tCIDLib::VOID __CreatePerThreadObjs();
  402.  
  403.         tCIDLib::VOID __DestroyPerThreadObjs();
  404.  
  405.  
  406.         // ---------------------------------------------------------------------
  407.         //  Private data members
  408.         //
  409.         //  __apobjList
  410.         //      This is the array of per-thread objects. It is filled in by the
  411.         //      constructor and cleaned up by the destructor. It holds the
  412.         //      per-thread objects. The current number of valid entries is
  413.         //      known inside the .Cpp module.
  414.         //
  415.         //  __bRunning
  416.         //      Set if the thread is currently running. It is cleared when the
  417.         //      thread function returns.
  418.         //
  419.         //  __bSelfPrio
  420.         //      This flag (when set) prevents any other thread from setting
  421.         //      this thread's priority.
  422.         //
  423.         //  __bSyncRequest
  424.         //      This is set to indicate that another thread has called
  425.         //      bWaitSync(). It is also used to make sure that two threads
  426.         //      don't try to sync at the same time. We store the tid of the
  427.         //      syncing thread to be able to insure that only he releases
  428.         //      the sync (in __tidSyncRequester.)
  429.         //
  430.         //  __c4StackSz
  431.         //      The size of the stack to give to the thread. Passed in by the
  432.         //      creator.
  433.         //
  434.         //  __perrLast
  435.         //      Storage for the last error that occured. Each time a new error
  436.         //      is stored (via StoreNewError()), the old one is deleted and the
  437.         //      new one is stored here. Only copies are returned to callers so
  438.         //      there is no problem with this. It is also deleted when the
  439.         //      client calls to get the error info. This leaves the error info
  440.         //      cleared until the next error.
  441.         //
  442.         //  __hevSync
  443.         //      This semaphore is used by the Sync()/WaitSync() methods to
  444.         //      allow the thread to sync with another thread. It is also used
  445.         //      during thread startup to sync.
  446.         //
  447.         //  __hevResponse
  448.         //      This semaphore is used by the Sync()/WaitSync() methods to
  449.         //      allow the thread to sync with another thread.
  450.         //
  451.         //  __pfnFunc
  452.         //      This is the address of the function that will be the entry
  453.         //      point of the thread. It is called from the .bStart() method.
  454.         //      When it returns, the destructor is called.
  455.         //
  456.         //  __pfnOnExit
  457.         //      This is the address of an optional on-exit function that
  458.         //      may be provided by the client code. It will be called when
  459.         //      the thread is shutting down. If the client does not set the
  460.         //      function, it is 0.
  461.         //
  462.         //  __pData
  463.         //      A pointer to the data buffer that was passed to the thread.
  464.         //
  465.         //  __tidSyncReq
  466.         //      When a sync request is made, we store the id of the thread
  467.         //      that is syncing. This allows us to make sure that only that
  468.         //      thread releases the sync.
  469.         //
  470.         //  __tidThread
  471.         //      The thread id for this thread. This is used later to identify
  472.         //      this thread and get its name for error reported.
  473.         //
  474.         //  __szName
  475.         //      The name of the thread. This was passed in by the caller in the
  476.         //      constructor.
  477.         // ---------------------------------------------------------------------
  478.         CIDOBJECT*              __apobjList[c4MaxPTObjs];
  479.         tCIDLib::eBOOL          __bRunning;
  480.         tCIDLib::eBOOL          __bSelfPrio;
  481.         tCIDLib::eBOOL          __bSyncRequest;
  482.         tCIDLib::CARD4          __c4StackSz;
  483.         CIDERROR*               __perrLast;
  484.         HEV                     __hevSync;
  485.         HEV                     __hevResponse;
  486.         tCIDLib::pfnTHREADFUNC  __pfnFunc;
  487.         tCIDLib::pfnEXITFUNC    __pfnOnExit;
  488.         tCIDLib::VOID*          __pData;
  489.         TID                     __tidSyncReq;
  490.         TID                     __tidThread;
  491.         STRG32                  __strName;
  492. };
  493.  
  494.  
  495. //
  496. //  Some global functions for formatting our enumerated values. The actual
  497. //  functions are in CIDLib_FmtType.Cpp.
  498. //
  499. STRGBUF& operator<<(STRGBUF& strDest, tCIDLib::ePRTYCLASS ePrtyClass);
  500. OTXTFILE& operator<<(OTXTFILE& txflDest, tCIDLib::ePRTYCLASS ePrtyClass);
  501.  
  502. #endif
  503.