home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
VSCPPv8.zip
/
VACPP
/
IBMCPP
/
samples
/
TOOLKIT
/
PM
/
TEMPLATE
/
THRD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-17
|
15KB
|
412 lines
/**************************************************************************
* File name : thrd.c
*
* Description: 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 need not 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 such as
* WinMsgSemWait().
*
* The BackgroundThread() routine is designed to create only
* one thread. 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()
* CreateBackgroundThread()
* DestroyBackgroundThread()
* PostBkThreadMsg(msg, mp1, mp2)
* SendBkThreadMsg(msg, mp1, mp2)
* ObjectWndProc(hwnd, msg, mp1, mp2)
*
* Concepts : background thread
*
* API's : WinInitialize
* WinPostMsg
* DosExit
* WinCreateMsgQueue
* WinTerminate
* WinLoadString
* WinRegisterClass
* WinCreateWindow
* DosPostEventSem
* WinGetMsg
* WinDispatchMsg
* WinIsWindow
* WinDestroyWindow
* WinDestroyMsgQueue
* DosCreateEventSem
* DosCreateThread
* WinWaitEventSem
* DosWaitThread
* WinDefWindowProc
*
* Required
* Files : OS2.H, MAIN.H, XTRN.H
*
* Copyright (C) 1991 IBM Corporation
*
* DISCLAIMER OF WARRANTIES. The following [enclosed] code is
* sample code created by IBM Corporation. This sample code is not
* part of any standard or IBM product and is provided to you solely
* for the purpose of assisting you in the development of your
* applications. The code is provided "AS IS", without
* warranty of any kind. IBM shall not be liable for any damages
* arising out of your use of the sample code, even if they have been
* advised of the possibility of such damages. *
*************************************************************************/
/*
* 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 */
VOID BackgroundThread (ULONG);
MRESULT EXPENTRY ObjectWndProc(HWND, ULONG, MPARAM, MPARAM);
/**************************************************************************
*
* Name : BackgroundThread(ulThreadParam)
*
* Description: Routine is a background thread used for tasks to be
* completed in the background.
*
* Concepts: Routine is called at initialization time to create
* a background processing thread.
*
* 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.
*
* API's : WinInitialize
* WinPostMsg
* DosExit
* WinCreateMsgQueue
* WinLoadString
* WinRegisterClass
* WinCreateWindow
* DosPostEventSem
* WinGetMsg
* WinDispatchMsg
* WinIsWindow
* WinDestroyWindow
* WinDestroyMsgQueue
*
* Parameters : ulThreadParam = thread parameter
*
* Return : [none]
*
*************************************************************************/
VOID BackgroundThread(ULONG ulThreadParam)
{
QMSG qmsg;
/* create message queue for thread */
habBkThread = WinInitialize(0);
if(habBkThread == NULLHANDLE)
{
WinPostMsg(hwndMain, TM_THREADINITFAILED, (MPARAM)NULL, (MPARAM)NULL);
DosExit(EXIT_THREAD, 0L);
}
hmqBkThread = WinCreateMsgQueue(habBkThread, 0);
if(hmqBkThread == NULLHANDLE)
{
WinPostMsg(hwndMain, TM_THREADINITFAILED, (MPARAM)NULL, (MPARAM)NULL);
WinTerminate(habBkThread);
DosExit(EXIT_THREAD, 0L);
}
/* load the string for the object window class and register the class */
if(WinLoadString(habBkThread,
(HMODULE)NULLHANDLE,
IDS_OBJECTCLASS,
MAXNAMEL,
(PSZ)szObjectClass)
&&
/* register the main client window class */
WinRegisterClass(habBkThread,
(PSZ)szObjectClass,
(PFNWP)ObjectWndProc,
0L,
0L)
&&
/* create the object window */
(NULLHANDLE != (hwndObject = WinCreateWindow(HWND_OBJECT,
(PSZ)szObjectClass,
(PSZ)NULL,
0L,
0L,
0L,
0L,
0L,
(HWND)NULLHANDLE,
HWND_TOP,
OBJECTID,
(PVOID)NULL,
(PVOID)NULL))))
{
/* set thread created flag so another thread of this type
* cannot be created.
*/
fThreadCreated = TRUE;
/* clear initialization semaphore */
DosPostEventSem(hevThreadInit);
/* message loop */
while(WinGetMsg(habBkThread, &qmsg, (HWND)NULLHANDLE, 0L, 0L))
WinDispatchMsg(habBkThread, &qmsg);
}
else
{
WinPostMsg(hwndMain, TM_THREADINITFAILED, NULL, NULL);
}
/* 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);
DosExit(EXIT_THREAD, 0L);
/* the thread parameter is not currently used */
ulThreadParam;
} /* End of BackgroundThread */
/**************************************************************************
*
* Name : CreateBackgroundThread()
*
* Description: Creates the background thread
*
* Concepts: Routine is called at initialization time to create
* a background processing thread.
*
* The routine calls DosCreateThread with the Background
* thread routine.
*
* API's : DosCreateEventSem
* DosCreateThread
* WinWaitEventSem
*
* Parameters : [none]
*
* Return : TRUE = thread is created successfully
* FALSE = not, or if the thread was already created
*
*************************************************************************/
BOOL CreateBackgroundThread(VOID)
{
ULONG sRet;
if(!fThreadCreated)
{
DosCreateEventSem((PSZ)NULL, &hevThreadInit, 0L, FALSE);
sRet = (ULONG)DosCreateThread(&tidBkThread,
(PFNTHREAD)BackgroundThread,
0L,
0L,
THREADSTACKSIZE);
}
else
return FALSE;
/* wait until the thread has finished initialization */
if(WinWaitEventSem(hevThreadInit, SEM_TIMEOUT))
return FALSE;
return((BOOL)(sRet == 0L));
} /* End of CreateBackgroundThread */
/**************************************************************************
*
* Name : DestroyBackgroundThread()
*
* Description: Destroys the background thread
*
* Concepts: Routine is called at exit time to destroy the
* background processing thread.
*
* 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.
*
* API's : DosWaitThread
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID DestroyBackgroundThread(VOID)
{
PostBkThreadMsg(WM_CLOSE, (MPARAM)NULL, (MPARAM)NULL);
DosWaitThread(&tidBkThread, 0L);
} /* End of DestroyBackgroundThread */
/**************************************************************************
*
* Name : PostBkThreadMsg(msg, mp1, mp2)
*
* Description: Routine posts a message to the object window of the
* background thread.
*
* Concepts: Routine is called whenever a message is to be posted to
* the background processing thread.
*
* The routine posts the message to the object window of the
* thread.
*
* API's : WinPostMsg
*
* Parameters : msg = the message i.d.
* mp1 = first message parameter
* mp2 = second message parameter
*
* Return : the return value from WinPostMsg().
*
*************************************************************************/
BOOL PostBkThreadMsg(ULONG msg, MPARAM mp1, MPARAM mp2)
{
return(WinPostMsg(hwndObject, msg, mp1, mp2));
} /* End of PostBkThreadMsg */
/**************************************************************************
*
* Name : SendBkThreadMsg(msg, mp1, mp2)
*
* Description: Routine sends a message to the object window of the
* background thread.
*
* Concepts: Routine is called whenever a message is to be sent to
* the background processing thread.
*
* The routine sends the message to the object window of the
* thread.
*
* API's : WinSendMsg
*
* Parameters : msg = the message i.d.
* mp1 = first message parameter
* mp2 = second message parameter
*
* Return : the return value from WinSendMsg().
*
*************************************************************************/
MRESULT SendBkThreadMsg(ULONG msg, MPARAM mp1, MPARAM mp2)
{
return(WinSendMsg(hwndObject, msg, mp1, mp2));
} /* End of SendBkThreadMsg */
/**************************************************************************
*
* Name : ObjectWndProc(hwnd, msg, mp1, mp2)
*
* Description: Processes all messages sent to the Object window
*
* Concepts: Called for each message sent to the Object window.
*
* 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.
*
* API's : WinDefWindowProc
*
* Parameters : hwnd= window handle
* msg = the message i.d.
* mp1 = first message parameter
* mp2 = second message parameter
*
* Return : dependent on message sent
*
*************************************************************************/
MRESULT EXPENTRY ObjectWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
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 (MRESULT)NULL;
} /* End of ObjectWndProc */
/*************************** End of thrd.c ****************************/