home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / rpc / mandel / remote.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-11  |  9.2 KB  |  359 lines

  1. /****************************************************************************
  2.                    Microsoft RPC Version 2.0
  3.            Copyright Microsoft Corp. 1992, 1993, 1994- 1996
  4.                         mandel Example
  5.  
  6.     FILE:      remote.c
  7.  
  8.     PURPOSE:   Client side of the RPC distributed application Mandel
  9.  
  10.     COMMENTS:  Code to do the remote calculations for the Windows
  11.                Mandelbrot Set distributed drawing program.
  12.  
  13.                Information coming into this module (via API calls) is
  14.                based on upper-left being (0,0) (the Windows standard).
  15.                We translate that to lower-left is (0,0) before we ship
  16.                it out onto the net, and we do reverse translations
  17.                accordingly.
  18.  
  19.                The iteration data is passed back to the main window
  20.                procedure (by means of a WM_PAINTLINE message) which
  21.                draws the picture.
  22.  
  23.                A word about the shared buffer: multiple buffers could
  24.                be used, but a single one is used. The buffer is requested
  25.                in this code, and then released after the data has been
  26.                drawn (in PaintLine() in mandel.c). So long as the painting
  27.                is done quickly, this is efficient.
  28.  
  29. ****************************************************************************/
  30.  
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <windows.h>
  35.  
  36. #ifdef RPC
  37. #include "mdlrpc.h"
  38. #endif
  39. #include "mandel.h"
  40.  
  41.  
  42. /*
  43.  * External variables
  44.  */
  45. extern int          fBound;
  46. extern svr_table    SvrTable;    // the server table
  47. extern int          iLines;
  48. extern double       dPrec;
  49. extern int          fContinueZoom;
  50. extern int          fZoomIn;
  51. extern int          iHistMaxI;
  52. extern int          iHistMaxJ;
  53. extern RECT         rcZoom;
  54. extern BOOL         fRectDefined;
  55.  
  56.  
  57. /*
  58.  * Picture information
  59.  */
  60. int             cPictureID = 0;    // picture id, in case we reset in the middle
  61. static CPOINT   cptLL;             // upper-left
  62. static double   dPrecision;        // precision of draw
  63. static LONGRECT rclPicture;        // rectangle defining client window
  64. static DWORD    dwCurrentLine;     // next line to be drawn
  65. static DWORD    dwThreshold;       // threshold for iterations
  66.  
  67. /*
  68.  * Function prototypes for local procs
  69.  */
  70. DWORD CalcThreshold(double);
  71.  
  72.  
  73. /*
  74.  *  InitRemote --
  75.  *
  76.  *  This function initializes everything for our remote connections.
  77.  *  It gets the local wksta name (making sure the wksta is started)
  78.  *  and it creates the mailslot with which to collect replies to our poll.
  79.  *
  80.  *  RETURNS
  81.  *      TRUE    - initialization succeeded
  82.  *      FALSE   - initialization failed, can't go on
  83.  */
  84.  
  85. BOOL InitRemote(HWND hWnd)
  86. {
  87.  
  88. #ifndef RPC
  89.     UNREFERENCED_PARAMETER(hWnd);
  90. #endif
  91.  
  92.     // set up our local entry
  93.     strcpy(SvrTable.name, "Local machine");
  94.     SvrTable.iStatus = SS_LOCAL;
  95.  
  96.     // good, we succeeded
  97.     return(TRUE);
  98. }
  99.  
  100.  
  101. /*
  102.  *  CheckDrawStatus --
  103.  *
  104.  *  This function does a check of all buffers being drawn.
  105.  *
  106.  *  If it finds an idle pipe, and there is work to be done, it assigns
  107.  *      a line, and writes out the request.
  108.  *  If it finds a read-pending pipe, it checks if the read has completed.
  109.  *      If it has, it is read and a message is sent so the read data can
  110.  *      be processed.
  111.  *
  112.  *  RETURNS
  113.  *      TRUE    - we did a piece of work
  114.  *      FALSE   - we could not find any work to do.
  115.  */
  116.  
  117. BOOL CheckDrawStatus(HWND hwnd)
  118. {
  119.     CALCBUF     cb;
  120.     LPVOID      pbBuf;
  121.  
  122.     while(TRUE) {
  123.  
  124.         // Check the status
  125.         switch(SvrTable.iStatus) {
  126.  
  127.         case SS_PAINTING:
  128.             break;
  129.  
  130.         case SS_IDLE:
  131.             break;
  132.  
  133.         case SS_LOCAL:
  134.             // Do a chunk of work locally
  135.  
  136. #ifdef RPC
  137.             if (fBound == FALSE)
  138.                 break;
  139. #endif
  140.  
  141.             if ((long) dwCurrentLine > rclPicture.xRight) {
  142.                 if (fContinueZoom == TRUE) {
  143.                     if ((fZoomIn == TRUE) && (dPrec < (double)MINPREC))
  144.                         fZoomIn = FALSE;  // start zooming out
  145.                     if ((fZoomIn == FALSE) && (dPrec > (double)MAXPREC))
  146.                         fZoomIn = TRUE;
  147.                     if (fZoomIn) {
  148.                         CountHistogram();
  149.                         rcZoom.top    = iHistMaxJ * (WIDTH/4);
  150.                         rcZoom.bottom = rcZoom.top + (WIDTH/4) - 1;
  151.                         rcZoom.left   = iHistMaxI * (HEIGHT/4);
  152.                         rcZoom.right  = rcZoom.left + (HEIGHT/4) - 1;
  153.                         fRectDefined = TRUE;
  154.                         PostMessage(hwnd, WM_COMMAND, IDM_ZOOMIN, 0L);
  155.                     }
  156.                     else
  157.                         PostMessage(hwnd, WM_COMMAND, IDM_ZOOMOUT, 0L);
  158.                 }
  159.                 break;
  160.             }
  161.  
  162.             if (TakeDrawBuffer() == FALSE)
  163.                 break;
  164.  
  165.             pbBuf = LockDrawBuffer();
  166.  
  167.             cb.rclDraw.xLeft = dwCurrentLine;
  168.             cb.rclDraw.xRight = dwCurrentLine + iLines - 1;
  169.             cb.rclDraw.yTop = rclPicture.yTop;
  170.             cb.rclDraw.yBottom = rclPicture.yBottom;
  171.  
  172.             RpcTryExcept {
  173.                 MandelCalc(&cptLL,
  174.                            &(cb.rclDraw),
  175.                            dPrecision,
  176.                            dwThreshold,
  177.                            (LINEBUF *) pbBuf);
  178.             }
  179.             RpcExcept(1) {
  180.                 char szFail[MSGLEN];
  181.  
  182.                 sprintf (szFail, "%s (0x%x)\n", EXCEPT_MSG, RpcExceptionCode());
  183.                 MessageBox(hwnd,
  184.                            szFail,
  185.                            "Remote Procedure Call",
  186.                            MB_ICONINFORMATION);
  187.                         KillTimer(hwnd, 1);  // stop timer for polls
  188.                     EnableMenuItem(GetMenu(hwnd), IDM_GO, MF_ENABLED);  // enable GO
  189.                     UnlockDrawBuffer();
  190.  
  191.                             ReturnDrawBuffer();
  192.                         return(FALSE);
  193.             }
  194.             RpcEndExcept
  195.  
  196.             UnlockDrawBuffer();
  197.  
  198.             SvrTable.cPicture = cPictureID;
  199.             SvrTable.dwLine = dwCurrentLine;
  200.             SvrTable.cLines = iLines;
  201.  
  202.             PostMessage(hwnd, WM_PAINTLINE, 0, 0L);
  203.             dwCurrentLine += iLines;
  204.  
  205.             return(TRUE);
  206.         }
  207.  
  208.         return(FALSE);
  209.     }
  210. }
  211.  
  212.  
  213. /*
  214.  *  SetNewCalc --
  215.  *
  216.  *  This sets up new information for a drawing and
  217.  *  updates the drawing ID so any calculations in progress will not
  218.  *  be mixed in.
  219.  */
  220.  
  221. void SetNewCalc(CPOINT cptUL, double dPrec, RECT rc)
  222. {
  223.     // First, translate from upper left to lower left
  224.     cptLL.real = cptUL.real;
  225.     cptLL.imag = cptUL.imag - (dPrec * (rc.bottom - rc.top));
  226.  
  227.     // Now the precision
  228.     dPrecision = dPrec;
  229.  
  230.     // The rectangle. Once again, translate.
  231.     rclPicture.xLeft = (long) rc.left;
  232.     rclPicture.xRight = (long) rc.right;
  233.     rclPicture.yBottom = (long) rc.top;
  234.     rclPicture.yTop = (long) rc.bottom;
  235.  
  236.     // Current line, start of drawing
  237.     dwCurrentLine = rclPicture.xLeft;
  238.  
  239.     dwThreshold = CalcThreshold(dPrecision);
  240. }
  241.  
  242.  
  243. void IncPictureID(void)
  244. {
  245.     cPictureID++;
  246. }
  247.  
  248.  
  249. void ResetPictureID(void)
  250. {
  251.     cPictureID = 0;
  252. }
  253.  
  254.  
  255. /*
  256.  *  CheckDrawing --
  257.  *
  258.  *  Just a sanity check here -- a function to check to make sure that we're
  259.  *  on the right drawing
  260.  */
  261.  
  262. BOOL CheckDrawingID(int id)
  263. {
  264.     return((id == cPictureID) ? TRUE : FALSE);
  265. }
  266.  
  267.  
  268. /*
  269.  *  TakeDrawBuffer ensures only one pipe read at a time.
  270.  *  LockDrawBuffer locks the handle and returns a pointer.
  271.  *  UnlockDrawBuffer unlocks the handle.
  272.  *  ReturnDrawBuffer lets another pipe read go.
  273.  *  FreeDrawBuffer ensures the allocated buffer is freed upon exit.
  274.  */
  275.  
  276. static BOOL fBufferTaken = FALSE;
  277. static HANDLE hSharedBuf = (HANDLE) NULL;
  278.  
  279.  
  280. BOOL TakeDrawBuffer(void)
  281. {
  282.     if (fBufferTaken) {
  283.         return(FALSE);
  284.     }
  285.  
  286.     if (hSharedBuf == (HANDLE) NULL) {
  287.         hSharedBuf = LocalAlloc(LMEM_MOVEABLE, MAX_BUFSIZE);
  288.         if (hSharedBuf == (HANDLE) NULL)
  289.             return(FALSE);
  290.     }
  291.  
  292.     fBufferTaken = TRUE;
  293.     return(TRUE);
  294. }
  295.  
  296.  
  297. LPVOID LockDrawBuffer(void)
  298. {
  299.     if (hSharedBuf == (HANDLE) NULL)
  300.         return(NULL);
  301.  
  302.     return(LocalLock(hSharedBuf));
  303. }
  304.  
  305.  
  306. void UnlockDrawBuffer(void)
  307. {
  308.     LocalUnlock(hSharedBuf);
  309. }
  310.  
  311.  
  312. void ReturnDrawBuffer(void)
  313. {
  314.     fBufferTaken = FALSE;
  315. }
  316.  
  317.  
  318. void FreeDrawBuffer(void)
  319. {
  320.     if (hSharedBuf != (HANDLE) NULL)
  321.         LocalFree(hSharedBuf);
  322. }
  323.  
  324.  
  325. /*
  326.  *  CalcThreshold --
  327.  *
  328.  *  We need an iteration threshold beyond which we give up. We want it to
  329.  *  increase the farther we zoom in. This code generates a threshold value
  330.  *  based on the precision of drawing.
  331.  *
  332.  *  RETURNS
  333.  *      threshold calculated based on precision
  334.  */
  335.  
  336. DWORD CalcThreshold(double precision)
  337. {
  338.     DWORD   thres = 25;
  339.     double  multiplier = (double) 100.0;
  340.  
  341.     /* for every 100, multiply by 2 */
  342.     while ((precision *= multiplier) < (double)1.0)
  343.         thres *= 2;
  344.  
  345.     return(thres);
  346. }
  347.  
  348.  
  349. /*
  350.  *  QueryThreshold --
  351.  *
  352.  *  Callback for finding out what the current drawing's threshold is.
  353.  */
  354.  
  355. DWORD QueryThreshold(void)
  356. {
  357.     return(dwThreshold);
  358. }
  359.