Home arrow C++ arrow Page 5 - 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 / 208
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

TOOLS YOU CAN USE

advertisement
Multithreading in C++ - The Thread Control Panel
(Page 5 of 11 )

The code for the thread control panel is shown here. This file is called tcp.cpp.

// A thread control panel.
#include <map>
#include <windows.h>
#include "panel.h"
using namespace std;
const int NUMPRIORITIES = 5;
const int OFFSET = 2;
// Array of strings for priority list box.
char priorities[NUMPRIORITIES][80] = {
  "Lowest",
  "Below Normal",
  "Normal",
  "Above Normal",
  "Highest"
};
// A Thread Control Panel Class.
class ThrdCtrlPanel {
  // Information about the thread under control.
  struct ThreadInfo {
    HANDLE hThread; //  handle of thread
    int priority;   //  current priority
    bool suspended; //  true if suspended
    ThreadInfo(HANDLE ht, int p, bool s) {
      hThread = ht;
      priority = p;
      suspended = s;
    }
  };
  // This map holds a ThreadInfo for each
  // active thread control panel.
  static map<HWND, ThreadInfo> dialogmap;
public:
  // Construct a control panel.
  ThrdCtrlPanel(HINSTANCE hInst, HANDLE hThrd);
  // The control panel's callback function.
  static LRESULT CALLBACK ThreadPanel(HWND hwnd, UINT message,
                         WPARAM wParam, LPARAM lParam);
};
// Define static member dialogmap.
map<HWND, ThrdCtrlPanel::ThreadInfo> 
  ThrdCtrlPanel::dialogmap;
// Create a thread control panel. ThrdCtrlPanel::ThrdCtrlPanel(HINSTANCE hInst,
                            HANDLE hThrd)
{
  ThreadInfo ti(hThrd,
                GetThreadPriority(hThrd)+OFFSET,
                false);
  // Owner window is desktop.
  HWND hDialog = CreateDialog(hInst, "ThreadPanelDB",
                      NULL,
                      (DLGPROC) ThreadPanel);
  // Put info about this dialog box in the map. 
  dialogmap.insert(pair<HWND, ThreadInfo>(hDialog, ti));
  // Set the control panel's title.
  char str[80] = "Control Panel for Thread ";
  char str2[4];
  _itoa(dialogmap.size(), str2, 10);
  strcat(str, str2);
  SetWindowText(hDialog, str);
  // Offset each dialog box instance.
  MoveWindow(hDialog, 30*dialogmap.size(), 
           30*dialogmap.size(),
           300, 250, 1);
  // Update priority setting in the list box. 
  SendDlgItemMessage(hDialog, IDD_LB, LB_SETCURSEL, 
                        (WPARAM) ti.priority, 0);
  // Increase priority to ensure control. You can
  // change or remove this statement based on your
  // execution environment.
  SetThreadPriority(GetCurrentThread(),
                   THREAD_PRIORITY_ABOVE_NORMAL);
}
// Thread control panel dialog box callback function.
LRESULT CALLBACK ThrdCtrlPanel::ThreadPanel(HWND hwnd,
                                      UINT message,
                                      WPARAM wParam,
                                      LPARAM lParam)
{
  int i;
  HWND hpbRes, hpbSus, hpbTerm;
  switch(message) {
    case WM_INITDIALOG:
      // Initialize priority list box.
      for(i=0; i<NUMPRIORITIES i++) {
        SendDlgItemMessage(hwnd, IDD_LB,
            LB_ADDSTRING, 0, (LPARAM) priorities[i]);
        }
        // Set suspend and resume buttons for thread. 
        hpbSus = GetDlgItem(hwnd, IDD_SUSPEND);
        hpbRes = GetDlgItem(hwnd, IDD_RESUME);
        EnableWindow(hpbSus, true);  // enable Suspend
        EnableWindow(hpbRes, false); // disable Resume 
        return 1;
    case WM_COMMAND:
      map<HWND, ThreadInfo>::iterator p = dialogmap.find(hwnd);
    switch(LOWORD(wParam)) {
      case IDD_TERMINATE:
        TerminateThread(p->second.hThread, 0);
        // Disable Terminate button.
        hpbTerm = GetDlgItem(hwnd, IDD_TERMINATE); }
        EnableWindow(hpbTerm, false); // disable
        // Disable Suspend and Resume buttons.
        hpbSus = GetDlgItem(hwnd, IDD_SUSPEND);
        hpbRes = GetDlgItem(hwnd, IDD_RESUME);
        EnableWindow(hpbSus, false); // disable Suspend
        EnableWindow(hpbRes, false); // disable Resume
        return 1;
      case IDD_SUSPEND:
        SuspendThread(p->second.hThread);
        // Set state of the Suspend and Resume buttons.
        hpbSus = GetDlgItem(hwnd, IDD_SUSPEND);
        hpbRes = GetDlgItem(hwnd, IDD_RESUME);
        EnableWindow(hpbSus, false); // disable Suspend
        EnableWindow(hpbRes, true);  // enable Resume
        p->second.suspended = true;
        return 1;
      case IDD_RESUME:
        ResumeThread(p->second.hThread);
        // Set state of the Suspend and Resume buttons.
        hpbSus = GetDlgItem(hwnd, IDD_SUSPEND);
        hpbRes = GetDlgItem(hwnd, IDD_RESUME); /'
        EnableWindow(hpbSus, true);  // enable Suspend /'
        EnableWindow(hpbRes, false); // disable Resume
        p->second.suspended = false;
        return 1;
      case IDD_LB:
        // If a list box entry was clicked,
        // then change the priority.
        if(HIWORD(wParam)==LBN_DBLCLK) {
         p->second.priority = SendDlgItemMessage(hwnd,
                              IDD_LB, LB_GETCURSEL,/'
                              0, 0);
        SetThreadPriority(p->second.hThread,
                                    p->second.priority-OFFSET);
        }
        return 1;
      case IDCANCEL:
        // If thread is suspended when panel is closed,
        // then resume thread to prevent deadlock.
        if(p->second.suspended) {
           ResumeThread(p->second.hThread);
          p->second.suspended = false;
        }
        // Remove this thread from the list.
        dialogmap.erase(hwnd);
        // Close the panel.
        DestroyWindow(hwnd);?
        return 1;
        }
  }
  return 0;
}

The control panel requires the following resource file, called tcp.rc:

#include <windows.h>
#include "panel.h"
ThreadPanelDB DIALOGEX 20, 20, 140, 110
CAPTION "Thread Control Panel"
STYLE WS_BORDER | WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU
{
  DEFPUSHBUTTON "Done", IDCANCEL, 55, 80, 33, 14
  PUSHBUTTON "Terminate", IDD_TERMINATE, 10, 20, 42, 12 
  PUSHBUTTON "Suspend", IDD_SUSPEND, 10, 35, 42, 12
  PUSHBUTTON "Resume", IDD_RESUME, 10, 50, 42, 12
  LISTBOX IDD_LB, 65, 20, 63, 42, LBS_NOTIFY | WS_VISIBLE |
          WS_BORDER | WS_VSCROLL | WS_TABSTOP
  CTEXT "Thread Priority", IDD_TEXT1, 65, 8, 64, 10
  CTEXT "Change State", IDD_TEXT2, 0, 8, 64, 10
}

The control panel uses the following header file called panel.h:

#define IDD_LB           200
#define IDD_TERMINATE    202
#define IDD_SUSPEND      204
#define IDD_RESUME       206
#define IDD_TEXT1        208
#define IDD_TEXT2        209

To use the thread control panel, follow these steps:

  1. Include tcp.cpp in your program.

  2. Include tcp.rc in your program’s resource file.

  3. Create the thread or threads that you want to control.

  4. Instantiate a ThrdCtrlPanel object for each thread.

Each ThrdCtrlPanel object links a thread with a dialog box that controls it. For large projects in which multiple files need access to ThrdCtrlPanel, you will need to use a header file called tcp.h that contains the declaration for ThrdCtrlPanel. Here is tcp.h:

// A header file for the ThrdCtrlPanel class.
class ThrdCtrlPanel {
public:
  // Construct a control panel.
  ThrdCtrlPanel(HINSTANCE hInst, HANDLE hThrd);
  // The control panel's callback function.
  static LRESULT CALLBACK ThreadPanel(HWND hwnd, UINT message,
                         WPARAM wParam, LPARAM lParam);
};


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++

Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 



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