|
|
1.1 root 1: /*
2: * REMOTE.C --
3: *
4: * Code to do the remote calculations for the Windows Mandelbrot Set
5: * distributed drawing program.
6: *
1.1.1.2 root 7: * Copyright (C) 1990, 1992 Microsoft Corporation.
1.1 root 8: *
9: * Information coming into this module (via API calls) is based on
10: * upper-left being (0,0) (the Windows standard). We translate that
1.1.1.2 root 11: * to lower-left is (0,0) before we ship it out onto
1.1 root 12: * the net, and we do reverse translations accordingly.
13: *
14: * The iteration data is passed back to the main window procedure
15: * (by means of a WM_PAINTLINE message) which draws the picture.
16: *
17: * A word about the shared buffer: multiple buffers could be used, but
18: * a single one is used. The buffer is requested in this code, and
19: * then released after the data has been drawn (in PaintLine() in
20: * mandel.c). So long as the painting is done quickly, this is efficient.
21: *
22: * This code sample is provided for demonstration purposes only.
23: * Microsoft makes no warranty, either express or implied,
24: * as to its usability in any given situation.
25: */
26:
27:
28: #include <string.h>
29: #include <stdio.h>
30: #include <fcntl.h>
31: #include <sys\types.h>
32: #include <sys\stat.h>
33: #include <share.h>
34: #include <io.h>
35: #include <malloc.h>
36:
37: #include <windows.h>
38:
39: #ifdef RPC
40: #include <rpc.h>
41: #include "mdlrpc.h"
42: #endif
43: #include "mandel.h"
1.1.1.2 root 44:
1.1 root 45: /*
1.1.1.2 root 46: * Tuning parameters
1.1 root 47: */
48: #define SVR_TABLE_SZ 20
49: #define MAX_PIPENAME_SZ CCHMAXPATH
50:
51:
52: /*
53: * Manifests, to keep everything neat.
54: */
55:
56: extern int errno; // errno from c runtime
57:
58: /*
59: * Data structures
60: */
61: extern svr_table SvrTable[]; // the table
62: extern int SvrTableSz; // # of objects in it
63: char pszFail[255];
64:
65:
66: // Do we do local work?
67: BOOL fLocalWork = TRUE;
68: BOOL fRemoteWork = FALSE;
69:
70: static int fDisplay = TRUE; /* display a message box for debug */
71:
72: // Picture information
73:
74: int cPictureID = 0; // picture id, in case we reset in the middle
75: static CPOINT cptLL; // upper-left
76: static double dPrecision; // precision of draw
77: static LONGRECT rclPicture; // rectangle defining client window
78: static DWORD dwCurrentLine; // next line to be drawn
79: static DWORD dwThreshold; // threshold for iterations
80:
81:
82: static char szLocal[] = "Local machine";
83: #ifdef RPC
84: RPC_STATUS status; // returned by RPC API function
85: #endif
86: /*
87: * function prototypes for local procs
88: */
89:
90: DWORD CalcThreshold( double );
91:
92:
93:
94: /*
95: * InitRemote --
96: *
97: * This function initializes everything for our remote connections.
98: * It gets the local wksta name (making sure the wksta is started)
99: * and it creates the mailslot with which to collect replies to our poll.
100: *
101: * RETURNS
102: *
103: * TRUE - initialization succeeded
104: * FALSE - initialization failed, can't go on
105: */
106:
107:
108: BOOL
109: InitRemote( HWND hWnd )
110: {
1.1.1.2 root 111:
1.1 root 112: #ifndef RPC
113: UNREFERENCED_PARAMETER(hWnd);
114: #endif
115:
116: // set up our local entry
117: SvrTableSz++;
118: strcpy(SvrTable[0].name, szLocal);
119: SvrTable[0].iStatus = SS_LOCAL;
120:
121:
122: // good, we succeeded
123: return TRUE;
124: }
125:
126:
127: /*
128: * CheckDrawStatus --
129: *
130: * This function does a check of all buffers being drawn.
131: *
132: * If it finds an idle pipe, and there is work to be done, it assigns
133: * a line, and writes out the request.
134: * If it finds a read-pending pipe, it checks if the read has completed.
135: * If it has, it is read and a message is sent so the read data can
136: * be processed.
137: *
138: * RETURNS
139: * TRUE - we did a piece of work
140: * FALSE - we could not find any work to do.
141: */
142:
143: BOOL CheckDrawStatus( HWND hwnd)
144: {
145:
146: static int iWork = 0;
147: int iLast;
148: CALCBUF cb;
149: PDWORD pbBuf;
150:
151: // If no pipes, forget it
152: if (SvrTableSz == 0)
153: return FALSE;
154:
155: // Move on from where we left off
156:
157: iLast = iWork;
158:
159: while ( TRUE )
160: {
161: iWork++;
162:
163: if (iWork == SvrTableSz)
164: iWork = 0;
165:
166: // Check the status
167: switch(SvrTable[iWork].iStatus) {
168:
169: case SS_PAINTING:
170: break;
171:
172: case SS_IDLE:
173: // Idle; assign it a piece of work
174: if ((long)dwCurrentLine > rclPicture.xRight)
175: break;
176:
177: if (!fRemoteWork)
178: break;
179: // cb is of type CALCBUF;
180: // rectangle, precision, threshold and complex point
181: cb.rclDraw.xLeft = dwCurrentLine;
182: cb.rclDraw.xRight = dwCurrentLine + iLines - 1;
183: cb.rclDraw.yTop = rclPicture.yTop;
184: cb.rclDraw.yBottom = rclPicture.yBottom;
185: cb.dblPrecision = dPrecision;
186: cb.dwThreshold = dwThreshold;
187: cb.cptLL = cptLL;
188:
189: SvrTable[iWork].dwLine = dwCurrentLine;
190: dwCurrentLine += iLines;
191: SvrTable[iWork].iStatus = SS_READPENDING;
192: SvrTable[iWork].cPicture = cPictureID;
193: SvrTable[iWork].cLines = iLines;
194:
195: return TRUE;
196:
197: case SS_LOCAL:
1.1.1.3 ! root 198: // Do a chunk of work locally
! 199: #ifdef RPC
! 200: if (fBound == FALSE)
! 201: break;
! 202: #endif
1.1 root 203:
204: if ((long)dwCurrentLine > rclPicture.xRight) {
205: if (fContinueZoom == TRUE) {
206: if ((fZoomIn == TRUE) && (dPrec < (double)MINPREC))
207: fZoomIn = FALSE; // start zooming out
208: if ((fZoomIn == FALSE) && (dPrec > (double)MAXPREC))
209: fZoomIn = TRUE;
210: if (fZoomIn) {
211: CountHistogram();
212: rcZoom.top = iHistMaxJ * (WIDTH/4);
213: rcZoom.bottom = rcZoom.top + (WIDTH/4) - 1;
214: rcZoom.left = iHistMaxI * (HEIGHT/4);
215: rcZoom.right = rcZoom.left + (HEIGHT/4) - 1;
216: fRectDefined = TRUE;
217: PostMessage(hwnd, WM_COMMAND, IDM_ZOOMIN, 0L);
218: }
219: else
220: PostMessage(hwnd, WM_COMMAND, IDM_ZOOMOUT, 0L);
221: }
222: break;
223: }
224:
225: if (!TakeDrawBuffer())
226: break;
227:
228: pbBuf = GetDrawBuffer();
229:
230: cb.rclDraw.xLeft = dwCurrentLine;
231: cb.rclDraw.xRight = dwCurrentLine+ iLines-1;
232: cb.rclDraw.yTop = rclPicture.yTop;
233: cb.rclDraw.yBottom = rclPicture.yBottom;
234:
235:
236: MandelCalc(&cptLL,
237: &(cb.rclDraw),
238: dPrecision,
239: dwThreshold,
240: (PLINEBUF)pbBuf);
241:
242: FreeDrawBuffer();
243:
244: SvrTable[iWork].cPicture = cPictureID;
245: SvrTable[iWork].dwLine = dwCurrentLine;
246: SvrTable[iWork].cLines = iLines;
247:
248: PostMessage(hwnd, WM_PAINTLINE,
249: (UINT)iWork,
250: 0L);
251: dwCurrentLine += iLines;
252: return TRUE;
253:
254: }
255:
256:
257: // If we made the full loop, we're done
258: if (iWork == iLast)
259: return FALSE;
260: }
261: }
262:
263:
264: /*
265: * SetNewCalc --
266: *
267: * This sets up new information for a drawing and
268: * updates the drawing ID so any calculations in progress will not
269: * be mixed in.
270: */
271:
272: void SetNewCalc( CPOINT cptUL, double dPrec, RECT rc)
273: {
274:
275: /*
276: * First, the base point. We need to translate from upper left to
277: * lower left.
278: */
279:
280: cptLL.real = cptUL.real;
281: cptLL.imag = cptUL.imag - (dPrec * (rc.bottom - rc.top));
282:
283: // Now the precision
284: dPrecision = dPrec;
285:
286: // The rectangle. Once again, translate.
287: rclPicture.xLeft = (long) rc.left;
288: rclPicture.xRight = (long) rc.right;
289: rclPicture.yBottom = (long) rc.top;
290: rclPicture.yTop = (long) rc.bottom;
291:
292: // Current line, start of drawing
293: dwCurrentLine = rclPicture.xLeft;
294:
295: dwThreshold = CalcThreshold(dPrecision);
296:
297:
298: }
299:
300: void IncPictureID(void)
301: {
302: cPictureID++;
303: }
304:
305: /*
306: * CheckDrawing --
307: *
308: * Just a sanity check here -- a function to check to make sure that we're
309: * on the right drawing
310: */
311:
312: BOOL
313: CheckDrawingID( int id)
314: {
315: return (id == cPictureID) ? TRUE : FALSE;
316: }
317:
318:
319: /*
320: * TakeDrawBuffer/ GetDrawBuffer/ FreeDrawBuffer / ReturnDrawBuffer
321: *
322: * These functions hide a handle to a buffer of memory.
323: *
324: * TakeDrawBuffer ensures only one pipe read at a time.
325: * GetDrawBuffer locks the handle and returns a pointer.
326: * FreeDrawBuffer unlocks the handle.
327: * ReturnDrawBuffer unlocks the handle and lets another pipe read go.
328: */
329:
330: static BOOL fBufferTaken = FALSE;
1.1.1.3 ! root 331: static HANDLE hSharedBuf = (HANDLE)NULL;
1.1 root 332:
333:
334: BOOL
335: TakeDrawBuffer( void )
336: {
337:
338: if (fBufferTaken)
339: {
340: return FALSE;
341: }
342:
343: if (hSharedBuf == NULL)
344: {
1.1.1.2 root 345: hSharedBuf = GlobalAlloc(GMEM_MOVEABLE, MAX_BUFSIZE);
1.1 root 346: if (hSharedBuf == NULL)
347: return FALSE;
348: }
349: fBufferTaken = TRUE;
350: return TRUE;
351: }
352:
353:
354:
355: PDWORD
356: GetDrawBuffer( void )
357: {
358:
359: if (hSharedBuf == NULL)
360: return NULL;
361:
1.1.1.2 root 362: return (PDWORD) GlobalLock(hSharedBuf);
1.1 root 363: }
364:
365:
366:
367: void
368: FreeDrawBuffer( void )
369: {
1.1.1.2 root 370: GlobalUnlock(hSharedBuf);
1.1 root 371: }
372:
373:
374: void
375: ReturnDrawBuffer( void )
376: {
377: fBufferTaken = FALSE;
378: }
379:
380:
381:
382: /*
383: * CalcThreshold --
384: *
385: * We need an iteration threshold beyond which we give up. We want it to
386: * increase the farther we zoom in. This code generates a threshold value
387: * based on the precision of drawing.
388: *
389: * RETURNS
390: *
391: * threshold calculated based on precision
392: */
393:
394:
395: DWORD CalcThreshold(double precision)
396: {
397: DWORD thres = 25;
1.1.1.2 root 398: double multiplier = (double) 100.0;
1.1 root 399:
400: /* for every 100, multiply by 2 */
1.1.1.2 root 401: while ( (precision *= multiplier) < (double)1.0)
1.1 root 402: thres *= 2;
403:
404: return thres;
405: }
406:
407:
408:
409: /*
410: * QueryThreshold --
411: *
412: * Callback for finding out what the current drawing's threshold is.
413: */
414:
415: DWORD QueryThreshold( void )
416: {
417: return dwThreshold;
418: }
419:
420:
421: /*
422: *
423: * GetServerCount --
424: *
425: * Returns the number of servers in the table.
426: */
427:
428: int
429: GetServerCount( void )
430: {
431: return (int) SvrTableSz-1;
432: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.