⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap3.lst

📁 The Art of C++一书的配套源代码
💻 LST
📖 第 1 页 / 共 2 页
字号:
listing 1
// 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;  
}

listing 2
#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  
} 

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

listing 4
// 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); 
};

listing 5
// 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;  
} 

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

listing 7
#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  
}

listing 8
// A garbage collector that runs as a back ground task. 
   
#include <iostream>   
#include <list>   
#include <typeinfo>   
#include <cstdlib> 
#include <windows.h> 
#include <process.h> 
 
using namespace std;   
   
// To watch the action of the garbage collector, define DISPLAY. 
// #define DISPLAY   
   
// Exception thrown when an attempt is made to    
// use an Iter that exceeds the range of the    
// underlying object.   
//   
class OutOfRangeExc {   
  // Add functionality if needed by your application.   
};   
   
// Exception thrown when a time-out occurs  
// when waiting for access to hMutex.  
//    
class TimeOutExc {    
  // Add functionality if needed by your application.    
};    
 
// An iterator-like class for cycling through arrays   
// that are pointed to by GCPtrs. Iter pointers   
// ** do not ** participate in or affect garbage   
// collection.  Thus, an Iter pointing to   
// some object does not prevent that object   
// from being recycled.   
//   
template <class T> class Iter {   
  T *ptr;   // current pointer value   
  T *end;   // points to element one past end   
  T *begin; // points to start of allocated array   
  unsigned length; // length of sequence   
public:   
   
  Iter() {    
    ptr = end = begin = NULL;   
    length = 0;   
  }   
   
  Iter(T *p, T *first, T *last) {   
    ptr =  p;   
    end = last;   
    begin = first;   
    length = last - first;   
  }   
     
  // Return length of sequence to which this   
  // Iter points.   
  unsigned size() { return length; }   
   
  // Return value pointed to by ptr.   
  // Do not allow out-of-bounds access. 
  T &operator*() {    
    if( (ptr >= end) || (ptr < begin) )   
      throw OutOfRangeExc();   
    return *ptr;   
  }   
   
  // Return address contained in ptr.   
  // Do not allow out-of-bounds access. 
  T *operator->() {    
    if( (ptr >= end) || (ptr < begin) )   
      throw OutOfRangeExc();   
    return ptr;   
  }     
   
  // Prefix ++.   
  Iter operator++() {   
    ptr++;   
    return *this;   
  }   
   
  // Prefix --.   
  Iter operator--() {   
    ptr--;   
    return *this;   
  }   
   
  // Postfix ++.   
  Iter operator++(int notused) {   
    T *tmp = ptr;   
   
    ptr++;   
    return Iter<T>(tmp, begin, end);   
  }   
   
  // Postfix --.   
  Iter operator--(int notused) {   
    T *tmp = ptr;   
   
    ptr--;   
    return Iter<T>(tmp, begin, end);   
  }   
   
  // Return a reference to the object at the   
  // specified index. Do not allow out-of-bounds 
  // access. 
  T &operator[](int i) {   
    if( (i < 0) || (i >= (end-begin)) )   
      throw OutOfRangeExc();   
    return ptr[i];   
  }   
   
  // Define the relational operators.   
  bool operator==(Iter op2) {   
    return ptr == op2.ptr;   
  }   
   
  bool operator!=(Iter op2) {   
    return ptr != op2.ptr;   
  }   
   
  bool operator<(Iter op2) {   
    return ptr < op2.ptr;   
  }   
   
  bool operator<=(Iter op2) {   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -