home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / template.zip / THRD.C < prev    next >
C/C++ Source or Header  |  1998-04-20  |  15KB  |  412 lines

  1. /**************************************************************************
  2.  *  File name  :  thrd.c
  3.  *
  4.  *  Description:  This module contains the code for a background processing
  5.  *                thread as well as the code for any routines used in that
  6.  *                thread.
  7.  *
  8.  *                This thread uses an object window to facilitate
  9.  *                communication with the main thread.  The main thread can
  10.  *                communicate with the background thread through messages.
  11.  *                You define your own window messages in main.h, post or send
  12.  *                them to the background thread through the routines provided
  13.  *                in this file, and then process the messages in the
  14.  *                ObjectWndProc() routine.  The object window then sends
  15.  *                other messages back to the main window to notify the main
  16.  *                window as to the status of the task or with the final
  17.  *                result.
  18.  *
  19.  *                An object window is used as the main window of the thread
  20.  *                for several reasons.  The window is hidden, so it is
  21.  *                never displayed on the screen.  Since it is hidden, the
  22.  *                window does not have to process most of the window
  23.  *                messages that are processed by visible windows, e.g.
  24.  *                WM_PAINT, WM_SIZE, WM_SETFOCUS, etc.  This window will
  25.  *                never receive the focus so it need not process input
  26.  *                messages.  You can, however, send all mouse and keyboard
  27.  *                messages to this window and have it process all input if
  28.  *                you wish.  Since the window does not belong to any focus
  29.  *                or activation chains, you can block this thread on a
  30.  *                semaphore without having the system lock up or use the
  31.  *                window manager semaphore routines such as
  32.  *                WinMsgSemWait().
  33.  *
  34.  *                The BackgroundThread() routine is designed to create only
  35.  *                one thread.  Should you try to create another one, the
  36.  *                call will fail.  The thread uses several variables
  37.  *                which are defined globally within this module.  In order
  38.  *                to enable this routine to create multiple threads, you
  39.  *                will need to make these variables local.  You will also
  40.  *                need to differentiate between the different object
  41.  *                windows created so that you can specify which thread will
  42.  *                receive a posted message.
  43.  *
  44.  *                In order to enable the use of the second thread, define
  45.  *                the BACKGROUND_THREAD constant found in main.h.
  46.  *
  47.  *                This source file contains the following functions:
  48.  *
  49.  *                BackgroundThread()
  50.  *                CreateBackgroundThread()
  51.  *                DestroyBackgroundThread()
  52.  *                PostBkThreadMsg(msg, mp1, mp2)
  53.  *                SendBkThreadMsg(msg, mp1, mp2)
  54.  *                ObjectWndProc(hwnd, msg, mp1, mp2)
  55.  *
  56.  *  Concepts   :  background thread
  57.  *
  58.  *  API's      :  WinInitialize
  59.  *                WinPostMsg
  60.  *                DosExit
  61.  *                WinCreateMsgQueue
  62.  *                WinTerminate
  63.  *                WinLoadString
  64.  *                WinRegisterClass
  65.  *                WinCreateWindow
  66.  *                DosPostEventSem
  67.  *                WinGetMsg
  68.  *                WinDispatchMsg
  69.  *                WinIsWindow
  70.  *                WinDestroyWindow
  71.  *                WinDestroyMsgQueue
  72.  *                DosCreateEventSem
  73.  *                DosCreateThread
  74.  *                WinWaitEventSem
  75.  *                DosWaitThread
  76.  *                WinDefWindowProc
  77.  *
  78.  *  Required
  79.  *    Files    :  OS2.H, MAIN.H, XTRN.H
  80.  *
  81.  *  Copyright (C) 1991 IBM Corporation
  82.  *
  83.  *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
  84.  *      sample code created by IBM Corporation. This sample code is not
  85.  *      part of any standard or IBM product and is provided to you solely
  86.  *      for  the purpose of assisting you in the development of your
  87.  *      applications.  The code is provided "AS IS", without
  88.  *      warranty of any kind.  IBM shall not be liable for any damages
  89.  *      arising out of your use of the sample code, even if they have been
  90.  *      advised of the possibility of such damages.                                                    *
  91.  *************************************************************************/
  92. /*
  93.  *  Include files, macros, defined constants, and externs
  94.  */
  95.  
  96. #define  INCL_DOSPROCESS
  97. #define  INCL_DOSSEMAPHORES
  98. #define  INCL_WINMESSAGEMGR
  99. #include <os2.h>
  100. #include "main.h"
  101. #include "xtrn.h"
  102.  
  103. #define THREADSTACKSIZE     8192L
  104. #define SEM_TIMEOUT        10000L
  105.  
  106. /*
  107.  *  Global variables
  108.  */
  109. static HAB habBkThread;
  110. static HMQ hmqBkThread;
  111. static TID tidBkThread;
  112. static HWND hwndObject;
  113. static CHAR szObjectClass[MAXNAMEL];
  114. static BOOL fThreadCreated = FALSE;
  115. static HEV hevThreadInit;   /* semaphore for thread initialization */
  116.  
  117. VOID BackgroundThread (ULONG);
  118.  
  119. MRESULT EXPENTRY ObjectWndProc(HWND, ULONG, MPARAM, MPARAM);
  120.  
  121. /**************************************************************************
  122.  *
  123.  *  Name       : BackgroundThread(ulThreadParam)
  124.  *
  125.  *  Description: Routine is a background thread used for tasks to be
  126.  *               completed in the background.
  127.  *
  128.  *  Concepts:    Routine is called at initialization time to create
  129.  *               a background processing thread.
  130.  *
  131.  *               The routine initializes itself as a PM thread and creates
  132.  *               a message queue.  It then creates an object window
  133.  *               through which it will receive and send messages.
  134.  *               It then polls through a message loop, processing any
  135.  *               messages it receives in the object window's window
  136.  *               procedure.  When the loop ends, it terminates.
  137.  *
  138.  *  API's      :  WinInitialize
  139.  *                WinPostMsg
  140.  *                DosExit
  141.  *                WinCreateMsgQueue
  142.  *                WinLoadString
  143.  *                WinRegisterClass
  144.  *                WinCreateWindow
  145.  *                DosPostEventSem
  146.  *                WinGetMsg
  147.  *                WinDispatchMsg
  148.  *                WinIsWindow
  149.  *                WinDestroyWindow
  150.  *                WinDestroyMsgQueue
  151.  *
  152.  *  Parameters :  ulThreadParam = thread parameter
  153.  *
  154.  *  Return     :  [none]
  155.  *
  156.  *************************************************************************/
  157. VOID BackgroundThread(ULONG ulThreadParam)
  158. {
  159.    QMSG qmsg;
  160.  
  161.    /* create message queue for thread */
  162.    habBkThread = WinInitialize(0);
  163.    if(habBkThread == NULLHANDLE)
  164.    {
  165.       WinPostMsg(hwndMain, TM_THREADINITFAILED, (MPARAM)NULL, (MPARAM)NULL);
  166.       DosExit(EXIT_THREAD, 0L);
  167.    }
  168.  
  169.    hmqBkThread = WinCreateMsgQueue(habBkThread, 0);
  170.    if(hmqBkThread == NULLHANDLE)
  171.    {
  172.       WinPostMsg(hwndMain, TM_THREADINITFAILED, (MPARAM)NULL, (MPARAM)NULL);
  173.  
  174.       WinTerminate(habBkThread);
  175.       DosExit(EXIT_THREAD, 0L);
  176.    }
  177.  
  178.    /* load the string for the object window class and register the class */
  179.    if(WinLoadString(habBkThread,
  180.                     (HMODULE)NULLHANDLE,
  181.                     IDS_OBJECTCLASS,
  182.                     MAXNAMEL,
  183.                     (PSZ)szObjectClass)
  184.       &&
  185.               /* register the main client window class */
  186.       WinRegisterClass(habBkThread,
  187.                        (PSZ)szObjectClass,
  188.                        (PFNWP)ObjectWndProc,
  189.                        0L,
  190.                        0L)
  191.       &&
  192.             /* create the object window */
  193.       (NULLHANDLE != (hwndObject = WinCreateWindow(HWND_OBJECT,
  194.                                     (PSZ)szObjectClass,
  195.                                     (PSZ)NULL,
  196.                                     0L,
  197.                                     0L,
  198.                                     0L,
  199.                                     0L,
  200.                                     0L,
  201.                                     (HWND)NULLHANDLE,
  202.                                     HWND_TOP,
  203.                                     OBJECTID,
  204.                                     (PVOID)NULL,
  205.                                     (PVOID)NULL))))
  206.    {
  207.       /* set thread created flag so another thread of this type
  208.        * cannot be created.
  209.        */
  210.       fThreadCreated = TRUE;
  211.  
  212.       /* clear initialization semaphore */
  213.       DosPostEventSem(hevThreadInit);
  214.  
  215.       /* message loop */
  216.       while(WinGetMsg(habBkThread, &qmsg, (HWND)NULLHANDLE, 0L, 0L))
  217.          WinDispatchMsg(habBkThread, &qmsg);
  218.    }
  219.    else
  220.    {
  221.       WinPostMsg(hwndMain, TM_THREADINITFAILED, NULL, NULL);
  222.    }
  223.  
  224.    /* destroy object window, clean up message queue and terminate */
  225.    if(WinIsWindow(habBkThread, hwndObject))
  226.       WinDestroyWindow(hwndObject);
  227.  
  228.    WinDestroyMsgQueue(hmqBkThread);
  229.    WinTerminate(habBkThread);
  230.  
  231.    /* If termination is due to an error initializing the thread, then
  232.        clear the initialization semaphore so that the main thread
  233.        can continue. */
  234.    if(!fThreadCreated)
  235.       DosPostEventSem(hevThreadInit);
  236.  
  237.    DosExit(EXIT_THREAD, 0L);
  238.  
  239.    /* the thread parameter is not currently used */
  240.    ulThreadParam;
  241. }   /* End of BackgroundThread */
  242.  
  243.  
  244. /**************************************************************************
  245.  *
  246.  *  Name       : CreateBackgroundThread()
  247.  *
  248.  *  Description: Creates the background thread
  249.  *
  250.  *  Concepts:    Routine is called at initialization time to create
  251.  *               a background processing thread.
  252.  *
  253.  *               The routine calls DosCreateThread with the Background
  254.  *               thread routine.
  255.  *
  256.  *  API's      :  DosCreateEventSem
  257.  *                DosCreateThread
  258.  *                WinWaitEventSem
  259.  *
  260.  *  Parameters :  [none]
  261.  *
  262.  *  Return     :  TRUE = thread is created successfully
  263.  *                FALSE = not, or if the thread was already created
  264.  *
  265.  *************************************************************************/
  266. BOOL CreateBackgroundThread(VOID)
  267. {
  268.    ULONG sRet;
  269.  
  270.    if(!fThreadCreated)
  271.    {
  272.       DosCreateEventSem((PSZ)NULL, &hevThreadInit, 0L, FALSE);
  273.       sRet = (ULONG)DosCreateThread(&tidBkThread,
  274.                                     (PFNTHREAD)BackgroundThread,
  275.                                     0L,
  276.                                     0L,
  277.                                     THREADSTACKSIZE);
  278.    }
  279.    else
  280.       return FALSE;
  281.  
  282.    /* wait until the thread has finished initialization */
  283.    if(WinWaitEventSem(hevThreadInit, SEM_TIMEOUT))
  284.       return FALSE;
  285.  
  286.    return((BOOL)(sRet == 0L));
  287. }   /* End of CreateBackgroundThread   */
  288.  
  289. /**************************************************************************
  290.  *
  291.  *  Name       : DestroyBackgroundThread()
  292.  *
  293.  *  Description: Destroys the background thread
  294.  *
  295.  *  Concepts:    Routine is called at exit time to destroy the
  296.  *               background processing thread.
  297.  *
  298.  *               The routine posts a WM_CLOSE message to the object window
  299.  *               to end its message loop.  It then waits to make sure that
  300.  *               the thread has been terminated before it returns.
  301.  *
  302.  *  API's      :  DosWaitThread
  303.  *
  304.  *  Parameters :  [none]
  305.  *
  306.  *  Return     :  [none]
  307.  *
  308.  *************************************************************************/
  309. VOID DestroyBackgroundThread(VOID)
  310. {
  311.    PostBkThreadMsg(WM_CLOSE, (MPARAM)NULL, (MPARAM)NULL);
  312.    DosWaitThread(&tidBkThread, 0L);
  313. }   /* End of DestroyBackgroundThread   */
  314.  
  315.  
  316. /**************************************************************************
  317.  *
  318.  *  Name       : PostBkThreadMsg(msg, mp1, mp2)
  319.  *
  320.  *  Description: Routine posts a message to the object window of the
  321.  *               background thread.
  322.  *
  323.  *  Concepts:    Routine is called whenever a message is to be posted to
  324.  *               the background processing thread.
  325.  *
  326.  *               The routine posts the message to the object window of the
  327.  *               thread.
  328.  *
  329.  *  API's      :  WinPostMsg
  330.  *
  331.  *  Parameters :  msg = the message i.d.
  332.  *                mp1 = first message parameter
  333.  *                mp2 = second message parameter
  334.  *
  335.  *  Return     :  the return value from WinPostMsg().
  336.  *
  337.  *************************************************************************/
  338. BOOL PostBkThreadMsg(ULONG msg, MPARAM mp1, MPARAM mp2)
  339. {
  340.    return(WinPostMsg(hwndObject, msg, mp1, mp2));
  341. }   /* End of PostBkThreadMsg   */
  342.  
  343.  
  344. /**************************************************************************
  345.  *
  346.  *  Name       : SendBkThreadMsg(msg, mp1, mp2)
  347.  *
  348.  *  Description: Routine sends a message to the object window of the
  349.  *               background thread.
  350.  *
  351.  *  Concepts:    Routine is called whenever a message is to be sent to
  352.  *               the background processing thread.
  353.  *
  354.  *               The routine sends the message to the object window of the
  355.  *               thread.
  356.  *
  357.  *  API's      :  WinSendMsg
  358.  *
  359.  *  Parameters :  msg = the message i.d.
  360.  *                mp1 = first message parameter
  361.  *                mp2 = second message parameter
  362.  *
  363.  *  Return     :  the return value from WinSendMsg().
  364.  *
  365.  *************************************************************************/
  366. MRESULT SendBkThreadMsg(ULONG msg, MPARAM mp1, MPARAM mp2)
  367. {
  368.    return(WinSendMsg(hwndObject, msg, mp1, mp2));
  369. }   /* End of SendBkThreadMsg   */
  370.  
  371.  
  372.  
  373. /**************************************************************************
  374.  *
  375.  *  Name       : ObjectWndProc(hwnd, msg, mp1, mp2)
  376.  *
  377.  *  Description: Processes all messages sent to the Object window
  378.  *
  379.  *  Concepts:    Called for each message sent to the Object window.
  380.  *
  381.  *               The Object window processes the messages that tell
  382.  *               the background thread what action to take.  Since
  383.  *               the object window is not visible, it will not
  384.  *               process any of the standard window messages.
  385.  *
  386.  *  API's      :  WinDefWindowProc
  387.  *
  388.  *  Parameters :  hwnd= window handle
  389.  *                msg = the message i.d.
  390.  *                mp1 = first message parameter
  391.  *                mp2 = second message parameter
  392.  *
  393.  *  Return     :  dependent on message sent
  394.  *
  395.  *************************************************************************/
  396. MRESULT EXPENTRY ObjectWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  397. {
  398.    switch(msg)
  399.    {
  400.        /*
  401.         *  Include any user-defined messages to determine which
  402.         *  action the background thread should take.
  403.         */
  404.  
  405.    default:
  406.       return (WinDefWindowProc(hwnd, msg, mp1, mp2));
  407.       break;
  408.    }
  409.    return (MRESULT)NULL;
  410. }   /* End of ObjectWndProc   */
  411. /***************************  End of thrd.c  ****************************/
  412.