|
|
Microsoft OS/2 SDK 2.0 05-30-1990
/*==============================================================*\
* Thrd.c - background thread and associated routines
* Created 1989, 1990 Microsoft Corp.
*--------------------------------------------------------------
*
* This module contains the code for a background processing
* thread as well as the code for any routines used in that thread.
*
* This thread uses an object window to facilitate communication
* with the main thread. The main thread can communicate with
* the background thread through messages. You define your
* own window messages in main.h, post or send them to the
* background thread through the routines provided in this file,
* and then process the messages in the ObjectWndProc() routine.
* The object window then sends other messages back to the
* main window to notify the main window as to the status of the
* task or with the final result.
*
* An object window is used as the main window of the thread
* for several reasons. The window is hidden, so it is never
* displayed on the screen. Since it is hidden, the window
* does not have to process most of the window messages that are
* processed by visible windows, e.g. WM_PAINT, WM_SIZE,
* WM_SETFOCUS, etc. This window will never receive the focus
* so it does not have to process input messages. You can, however,
* send all mouse and keyboard messages to this window and have
* it process all input if you wish. Since the window does not
* belong to any focus or activation chains, you can block this
* thread on a semaphore without having the system lock up or use
* the window manager semaphore routines (WinMsgSemWait(), etc.).
*
* NOTE: The BackgroundThread() routine is designed to create only
* one thread. In fact, should you try to create another
* one the call will fail. The thread uses several variables
* which are defined globally within this module. In order
* to enable this routine to create multiple threads, you
* will need to make these variables local. You will also need
* to differentiate between the different object windows
* created so that you can specify which thread will
* receive a posted message.
*
* In order to enable the use of the second thread, define the
* BACKGROUND_THREAD constant found in main.h
*
*--------------------------------------------------------------
*
* This source file contains the following functions:
*
* BackgroundThread() - routine for the background thread
* CreateBackgroundThread() - routine that creates background thread
* DestroyBackgroundThread() - routine that destroys the thread
* PostBkThreadMsg(msg, mp1, mp2) - posts a msg to the thread
* SendBkThreadMsg(msg, mp1, mp2) - sends a msg to the thread
* ObjectWndProc(hwnd, msg, mp1, mp2) - Object window procedure
*
\*==============================================================*/
/*--------------------------------------------------------------*\
* Include files, macros, defined constants, and externs
\*--------------------------------------------------------------*/
#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES
#include <os2.h>
#include "main.h"
#include "xtrn.h"
#define THREADSTACKSIZE 8192L
#define SEM_TIMEOUT 10000L
/*--------------------------------------------------------------*\
* Global variables
\*--------------------------------------------------------------*/
static HAB habBkThread;
static HMQ hmqBkThread;
static TID tidBkThread;
static HWND hwndObject;
static CHAR szObjectClass[MAXNAMEL];
static BOOL fThreadCreated = FALSE;
static HEV hevThreadInit; /* semaphore for thread initialization */
/*--------------------------------------------------------------*\
* Entry point declarations
\*--------------------------------------------------------------*/
VOID BackgroundThread(ULONG ulThreadParam);
MRESULT EXPENTRY ObjectWndProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
/****************************************************************\
* Background thread routine
*--------------------------------------------------------------
*
* Name: BackgroundThread(ulThreadParam)
*
* Purpose: Routine is a background thread used for tasks to be
* completed in the background.
*
* Usage: Routine is called at initialization time to create
* a background processing thread.
*
* Method: The routine initializes itself as a PM thread and creates
* a message queue. It then creates an object window
* through which it will receive and send messages.
* It then polls through a message loop, processing any
* messages it receives in the object window's window
* procedure. When the loop ends, it terminates.
*
* Returns:
*
\****************************************************************/
VOID BackgroundThread(ulThreadParam)
ULONG ulThreadParam; /* parameter passed into DosCreateThread() */
{
QMSG qmsg;
/* create message queue for thread */
habBkThread = WinInitialize(0);
if(habBkThread == NULL) {
WinPostMsg(hwndMain, TM_THREADINITFAILED, NULL, NULL);
DosExit(EXIT_THREAD, NULL);
}
hmqBkThread = WinCreateMsgQueue(habBkThread, 0);
if(hmqBkThread == NULL) {
WinPostMsg(hwndMain, TM_THREADINITFAILED, NULL, NULL);
WinTerminate(habBkThread);
DosExit(EXIT_THREAD, NULL);
}
/* load the string for the object window class and register the class */
if(!WinLoadString(habBkThread,
NULL,
IDS_OBJECTCLASS,
MAXNAMEL,
(PSZ)szObjectClass)) {
WinPostMsg(hwndMain, TM_THREADINITFAILED, NULL, NULL);
goto ExitBkThread;
}
/* register the main client window class */
if(!WinRegisterClass(habBkThread,
(PSZ)szObjectClass,
(PFNWP)ObjectWndProc,
0,
0)) {
WinPostMsg(hwndMain, TM_THREADINITFAILED, NULL, NULL);
goto ExitBkThread;
}
/* create the object window */
hwndObject = WinCreateWindow(HWND_OBJECT,
szObjectClass,
NULL,
NULL,
0,
0,
0,
0,
NULL,
HWND_TOP,
OBJECTID,
NULL,
NULL);
if(hwndObject == NULL) {
WinPostMsg(hwndMain, TM_THREADINITFAILED, NULL, NULL);
goto ExitBkThread;
}
/* set thread created flag so another thread of this type
cannot be created */
fThreadCreated = TRUE;
/* clear initialization semaphore */
DosPostEventSem(hevThreadInit);
/* message loop */
while(WinGetMsg(hmqBkThread, (PQMSG)&qmsg, NULL, NULL, NULL))
WinDispatchMsg(hmqBkThread, (PQMSG)&qmsg);
ExitBkThread:
/* destroy object window, clean up message queue and terminate */
if(WinIsWindow(habBkThread, hwndObject))
WinDestroyWindow(hwndObject);
WinDestroyMsgQueue(hmqBkThread);
WinTerminate(habBkThread);
/* If termination is due to an error initializing the thread, then
clear the initialization semaphore so that the main thread
can continue. */
if(!fThreadCreated)
DosPostEventSem(hevThreadInit);
/*------------------------------------------------------------------*
*
* Note: C-runtime considerations:
*
* If you use non-reentrant C runtime functions in the second thread,
* then you should use call _endthread here instead of DosExit().
* See the comment in the CreateBackgroundThread() routine for
* more information.
*
*------------------------------------------------------------------*/
DosExit(EXIT_THREAD, NULL);
/* the thread parameter is not currently used */
ulThreadParam;
} /* BackgroundThread() */
/****************************************************************\
* Creates the Background thread
*--------------------------------------------------------------
*
* Name: CreateBackgroundThread()
*
* Purpose: Routine creates the background thread
*
* Usage: Routine is called at initialization time to create
* a background processing thread.
*
* Method: The routine calls DosCreateThread with the Background
* thread routine.
*
* Returns: TRUE if thread is created successfully, FALSE if not
* or if the thread was already created
*
\****************************************************************/
BOOL CreateBackgroundThread(VOID)
{
SHORT sRet;
/*------------------------------------------------------------------*
*
* Note: C-runtime considerations:
*
* If you use non-reentrant C runtime functions in the second thread,
* then you will need to use _beginthread and _endthread instead of
* DosCreateThread and DosExit. In addition, you will have
* to link with LIBCMT.LIB instead of LIBC.LIB, and you will
* have use -D_MT as a compiler option.
*
*------------------------------------------------------------------*/
if(!fThreadCreated) {
DosCreateEventSem((PSZ)NULL, &hevThreadInit, 0L, FALSE);
sRet = DosCreateThread(&tidBkThread,
(PFNTHREAD)BackgroundThread,
0L,
0L,
THREADSTACKSIZE);
} else
return FALSE;
/* wait until the thread has finished initialization */
if(DosWaitEventSem(hevThreadInit, SEM_TIMEOUT))
return FALSE;
return((BOOL)(sRet == 0));
} /* CreateBackgroundThread() */
/****************************************************************\
* Destroys the Background thread
*--------------------------------------------------------------
*
* Name: DestroyBackgroundThread()
*
* Purpose: Routine destroys the background thread
*
* Usage: Routine is called at exit time to destroy the background
* processing thread.
*
* Method: The routine posts a WM_CLOSE message to the object window
* to end its message loop. It then waits to make sure that the
* thread has been terminated before it returns.
*
* Returns:
*
\****************************************************************/
VOID DestroyBackgroundThread(VOID)
{
PostBkThreadMsg(WM_CLOSE, NULL, NULL);
DosWaitThread(&tidBkThread, 0);
} /* DestroyBackgroundThread() */
/****************************************************************\
* Posts a message to the Background thread
*--------------------------------------------------------------
*
* Name: PostBkThreadMsg()
*
* Purpose: Routine posts a message to the object window of the
* background thread.
*
* Usage: Routine is called whenever a message is to be posted to
* the background processing thread.
*
* Method: The routine posts the message to the object window of the
* thread.
*
* Returns: the return value from WinPostMsg().
*
\****************************************************************/
BOOL PostBkThreadMsg(msg, mp1, mp2)
USHORT msg; /* message id */
MPARAM mp1; /* first parameter */
MPARAM mp2; /* second parameter */
{
return(WinPostMsg(hwndObject, msg, mp1, mp2));
} /* PostBkThreadMsg() */
/****************************************************************\
* Sends a message to the Background thread
*--------------------------------------------------------------
*
* Name: SendBkThreadMsg()
*
* Purpose: Routine sends a message to the object window of the
* background thread.
*
* Usage: Routine is called whenever a message is to be sent to
* the background processing thread.
*
* Method: The routine sends the message to the object window of the
* thread.
*
* Returns: the return value from WinSendMsg().
*
\****************************************************************/
MRESULT SendBkThreadMsg(msg, mp1, mp2)
USHORT msg; /* message id */
MPARAM mp1; /* first parameter */
MPARAM mp2; /* second parameter */
{
return(WinSendMsg(hwndObject, msg, mp1, mp2));
} /* SendBkThreadMsg() */
/****************************************************************\
* Dialog procedure for the Object window
*--------------------------------------------------------------
*
* Name: ObjectWndProc(hwnd, msg, mp1, mp2)
*
* Purpose: Processes all messages sent to the Object window
*
* Usage: Called for each message sent to the Object window.
*
* Method: the Object window processes the messages that tell
* the background thread what action to take. Since
* the object window is not visible, it will not
* process any of the standard window messages.
*
* Returns: Dependent upon message sent
*
\****************************************************************/
MRESULT EXPENTRY ObjectWndProc(hwnd, msg, mp1, mp2)
HWND hwnd; /* handle of window */
USHORT msg; /* id of message */
MPARAM mp1; /* first message parameter */
MPARAM mp2; /* second message parameter */
{
switch(msg) {
/*--------------------------------------------------------------*\
* Include any user defined messages to determine which
* action the background thread should take
\*--------------------------------------------------------------*/
default:
return (WinDefWindowProc(hwnd, msg, mp1, mp2));
break;
}
return 0L;
hwnd;
mp1;
mp2;
} /* ObjectWndProc() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.