Home arrow C++ arrow Page 7 - Multithreading in C++
C++

Multithreading in C++


Multithreading is growing in importance in modern programming for a variety of reasons, not the least of which being that Windows supports multithreading. While C++ does not feature built-in support for multithreading, it can be used to created multithreaded programs, which is the subject of this article. It is taken from chapter three of The Art of C++, written by Herbert Schildt (McGraw-Hill/Osborne, 2004; ISBN: 0072255129).

Author Info:
By: McGraw-Hill/Osborne
Rating: 5 stars5 stars5 stars5 stars5 stars / 229
July 14, 2005
TABLE OF CONTENTS:
  1. · Multithreading in C++
  2. · An Overview of the Windows Thread Functions
  3. · Priority Classes
  4. · The Windows Synchronization Objects
  5. · The Thread Control Panel
  6. · A Closer Look at the Thread Control Panel
  7. · Demonstrating the Control Panel
  8. · A Multithreaded Garbage Collector
  9. · Synchronizing Access to gclist
  10. · The Entire Multithreaded Garbage Collector
  11. · Using the Multithreaded Garbage Collector

print this article
SEARCH DEVARTICLES

Multithreading in C++ - Demonstrating the Control Panel
(Page 7 of 11 )

Here is a program that includes the thread control panel and demonstrates its use. Sample output is shown in Figure 3-2. The program creates a main window and defines two child threads. When started, these threads simply count from 0 to 50,000, displaying the count in the main window. These threads can be controlled by activating a thread control panel.

To use the program, first begin execution of the threads by selecting Start Threads from the Threads menu (or by pressing F2) and then activate the thread control panels by selecting Control Panels from the Threads menu (or by pressing F3). Once the control panels are active, you can experiment with different priority settings and so on.


Figure 3-2.  Sample output from the thread control panel sample program

NOTE


It is beyond the scope of this book to teach Windows programming. However, the operation of this sample program is straightforward and should be easily understood by all Windows programmers.

// Demonstrate the thread control panel.
#include <windows.h>
#include <process.h>
#include "thrdapp.h"
#include "tcp.cpp"
const int MAX = 500000;
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);
unsigned __stdcall MyThread1(void * param);
unsigned __stdcall MyThread2(void * param);
char str[255]; // holds output strings
unsigned tid1, tid2; // thread IDs
HANDLE hThread1, hThread2; // thread handles
HINSTANCE hInst; // instance handle
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
                   LPSTR args, int winMode)
{
  HWND hwnd;
  MSG msg;
  WNDCLASSEX wcl;
  HACCEL hAccel;
  // Define a window class.
  wcl.cbSize = sizeof(WNDCLASSEX);
  wcl.hInstance = hThisInst;     // handle to this instance
  wcl.lpszClassName = "MyWin";   // window class name
  wcl.lpfnWndProc = WindowFunc;  // window function
  wcl.style = 0;                 // default style
  wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); // large icon
  wcl.hIconSm = NULL; // use small version of large icon
  wcl.hCursor = LoadCursor(NULL, IDC_ARROW); // cursor style
  wcl.lpszMenuName = "ThreadAppMenu"; // main menu
  wcl.cbClsExtra = 0; // no extra memory needed
  wcl.cbWndExtra = 0;
  // Make the window background white.
  wcl.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  // Register the window class.
  if(!RegisterClassEx(&wcl)) return 0;
  /* Now that a window class has been registered, a window
     can be created. */
  hwnd = CreateWindow(
    wcl.lpszClassName, // name of window class
    "Using a Thread Control Panel", // title
    WS_OVERLAPPEDWINDOW, // window style - normal
    CW_USEDEFAULT, // X coordinate - let Windows decide
    CW_USEDEFAULT, // Y coordinate - let Windows decide
    260,           // width
    200,           // height
    NULL,          // no parent window
    NULL,          // no override of class menu
    hThisInst,     // instance handle
    NULL           // no additional arguments
  );
  hInst = hThisInst; // save instance handle
  // Load the keyboard accelerators.
  hAccel = LoadAccelerators(hThisInst, "ThreadAppMenu");
  // Display the window.
  ShowWindow(hwnd, winMode);
  UpdateWindow(hwnd);
  // Create the message loop.
  while(GetMessage(&msg, NULL, 0, 0))
  {
    if(!TranslateAccelerator(hwnd, hAccel, &msg)) {  
      TranslateMessage(&msg); // translate keyboard messages
      DispatchMessage(&msg); // return control to Windows
    }
  }
  return msg.wParam;
}
/* This function is called by Windows and is passed
   messages from the message queue.
*/
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message,
                            WPARAM wParam, LPARAM lParam)
{
  int response;
  switch(message) {
    case WM_COMMAND:
      switch(LOWORD(wParam)) {
        case IDM_THREAD: // create the threads
          hThread1 = (HANDLE) _beginthreadex(NULL, 0, 
                               MyThread1, (void *) hwnd,
                               0, &tid1);
          hThread2 = (HANDLE) _beginthreadex(NULL, 0,
                               MyThread2, (void *) hwnd,
                               0, &tid2);
          break;
        case IDM_PANEL: // activate control panel
          ThrdCtrlPanel(hInst, hThread1);
          ThrdCtrlPanel(hInst, hThread2);
          break;
        case IDM_EXIT:
          response = MessageBox(hwnd, "Quit the Program?",
                                "Exit", MB_YESNO);
          if(response == IDYES) PostQuitMessage(0);
          break;
        case IDM_HELP:
          MessageBox(hwnd,
                     "F1: Help\nF2: Start Threads\nF3: Panel",
                     "Help", MB_OK);
          break;
      }
      break;
    case WM_DESTROY: // terminate the program 
      PostQuitMessage(0);
      break;
    default:
     return DefWindowProc(hwnd, message, wParam, lParam);
  }
  return 0;
}
// First thread.
unsigned __stdcall MyThread1(void * param)
{
  int i;
  HDC hdc;
  for(i=0; i<MAX; i++) {
    wsprintf(str, "Thread 1: loop # %5d ", i);
    hdc = GetDC((HWND) param);
    TextOut(hdc, 1, 1, str, lstrlen(str));
    ReleaseDC((HWND) param, hdc);
  }
  return 0;
}
// Second thread.
unsigned __stdcall MyThread2(void * param)
{
  int i;
  HDC hdc;
  for(i=0; i<MAX; i++) {
    wsprintf(str, "Thread 2: loop # %5d ", i);
    hdc = GetDC((HWND) param);
    TextOut(hdc, 1, 20, str, lstrlen(str));
    ReleaseDC((HWND) param, hdc);
  }
  return 0;
}

This program requires the header file thrdapp.h, shown here:

#define IDM_THREAD      100
#define IDM_HELP        101
#define IDM_PANEL       102
#define IDM_EXIT        103

The resource file required by the program is shown here:

#include <windows.h>
#include "thrdapp.h"
#include "tcp.rc"
ThreadAppMenu MENU
{
  POPUP "&Threads" {
    MENUITEM "&Start Threads\tF2", IDM_THREAD
    MENUITEM "&Control Panels\tF3", IDM_PANEL
    MENUITEM "E&xit\tCtrl+X", IDM_EXIT
  }
  MENUITEM "&Help", IDM_HELP
}
ThreadAppMenu ACCELERATORS
{
  VK_F1, IDM_HELP, VIRTKEY
  VK_F2, IDM_THREAD, VIRTKEY
  VK_F3, IDM_PANEL, VIRTKEY
  "^X", IDM_EXIT
}


blog comments powered by Disqus
C++ ARTICLES

- Intel Threading Building Blocks
- Threading Building Blocks with C++
- Video Memory Programming in Text Mode
- More Tricks to Gain Speed in Programming Con...
- Easy and Efficient Programming for Contests
- Preparing For Programming Contests
- Programming Contests: Why Bother?
- Polymorphism in C++
- Overview of Virtual Functions
- Inheritance in C++
- Extending the Basic Streams in C++
- Using Stringstreams in C++
- Custom Stream Manipulation in C++
- General Stream Manipulation in C++
- Serialize Your Class into Streams in C++

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials