Annotation of os232sdk/toolkt20/c/samples/template/thrd.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.