|
|
1.1 ! root 1: /************************************************************************ ! 2: * ! 3: * lfthread.c -- Subroutines for thread management for LineFractal. ! 4: * ! 5: * Created by Microsoft Corporation, 1989 ! 6: * ! 7: ************************************************************************/ ! 8: ! 9: #define INCL_WIN ! 10: #define INCL_GPI ! 11: #define INCL_DOSSEMAPHORES ! 12: #define INCL_DOSMEMMGR ! 13: #define INCL_DOSPROCESS ! 14: #define INCL_DOSERRORS ! 15: #include <os2.h> ! 16: ! 17: #include <mt\process.h> ! 18: #include <mt\stddef.h> ! 19: ! 20: #define INCL_GLOBALS ! 21: #define INCL_THREADS ! 22: #include "linefrac.h" ! 23: ! 24: #define INCL_LFCMD ! 25: #define INCL_LFMAIN ! 26: #define INCL_LFPS ! 27: #define INCL_LFUTIL ! 28: #define INCL_LFTHREAD ! 29: #define INCL_LFDRAW ! 30: #include "lffuncs.h" ! 31: ! 32: ! 33: ! 34: ! 35: /************************************************************************ ! 36: * ! 37: * Global Variables ! 38: * ! 39: ************************************************************************/ ! 40: ! 41: extern GLOBALDATA global; ! 42: ! 43: ! 44: ! 45: ! 46: /************************************************************************ ! 47: * ! 48: * LfStartThread ! 49: * ! 50: * Do everything needed to start up a background thread drawing ! 51: * fractals. ! 52: * ! 53: * This includes: ! 54: * ! 55: * Allocate space for thread structure. ! 56: * Initialize fields of thread structure. ! 57: * Create a presentation space for the thread. ! 58: * Create stack space for the thread. ! 59: * Set the thread's semaphore to block -- i.e. don't start ! 60: * drawing until everything is ready. ! 61: * Start the thread. ! 62: * Set the thread's priority to idle time. ! 63: * ! 64: ************************************************************************/ ! 65: ! 66: #define SIZE_ACCUM_STACK 2048 ! 67: ! 68: PTHR ! 69: LfStartThread(dcType) ! 70: USHORT dcType; ! 71: { ! 72: PTHR pthr; ! 73: ! 74: ! 75: pthr = NULL; /* zero out all 32 bits */ ! 76: if (DosAllocSeg(sizeof(THR), ((PUSHORT)&pthr)+1, 0)) ! 77: return NULL; ! 78: ! 79: pthr->dcType = dcType; ! 80: ! 81: LfPreInitThread(pthr); ! 82: if (LfCreatePS(pthr)) ! 83: { ! 84: LfPostInitThread(pthr); ! 85: if (DosAllocSeg(SIZE_ACCUM_STACK, &pthr->selStack, 0)) ! 86: goto lfst_exit; ! 87: ! 88: DosSemSet(&pthr->lSemRedraw); ! 89: pthr->tid = _beginthread(LineFractalThread, MAKEP(pthr->selStack, 0), SIZE_ACCUM_STACK, pthr); ! 90: if (pthr->tid == -1) ! 91: { ! 92: LfDeletePS(pthr); ! 93: goto lfst_exit; ! 94: } ! 95: DosSetPrty(PRTYS_THREAD, PRTYC_IDLETIME, 0, pthr->tid); ! 96: ! 97: LfSelectXform(global.hwnd, pthr, pthr->usCurXform); ! 98: DosSemClear(&pthr->lSemRedraw); ! 99: ! 100: if (!DevQueryCaps(pthr->hdc, CAPS_HORIZONTAL_RESOLUTION, 2L, (PLONG)&(pthr->AspectRatio))) ! 101: { ! 102: pthr->AspectRatio.lHorz = 1L; ! 103: pthr->AspectRatio.lVert = 1L; ! 104: } ! 105: ! 106: return pthr; ! 107: } ! 108: lfst_exit: ! 109: DosFreeSeg(*(((PUSHORT)&pthr)+1)); ! 110: return NULL; ! 111: } ! 112: ! 113: ! 114: ! 115: ! 116: /************************************************************************ ! 117: * ! 118: * LfPreInitThread ! 119: * ! 120: * Initialize constant values in the thread structure needed from ! 121: * the moment the thread starts. If thread inheritance is enabled, ! 122: * then copy as much as possible from the top thread, if there is ! 123: * one. ! 124: * ! 125: ************************************************************************/ ! 126: ! 127: VOID ! 128: LfPreInitThread(pthr) ! 129: PTHR pthr; ! 130: { ! 131: pthr->hps = NULL; ! 132: pthr->hdc = NULL; ! 133: pthr->hbm = NULL; ! 134: pthr->fTimeToDie = FALSE; ! 135: pthr->fUpdateAttrs = FALSE; ! 136: pthr->fBusy = FALSE; ! 137: pthr->pptl = NULL; ! 138: pthr->cptl = 0; ! 139: pthr->pmatlf = NULL; ! 140: ! 141: if (global.fThreadInheritance && global.pThrTop) ! 142: { ! 143: pthr->cPlanes = global.pThrTop->cPlanes ; ! 144: pthr->cBitCount = global.pThrTop->cBitCount ; ! 145: ! 146: pthr->cxWCS = global.pThrTop->cxWCS ; ! 147: pthr->cyWCS = global.pThrTop->cyWCS ; ! 148: ! 149: pthr->fAutoSizePS = global.pThrTop->fAutoSizePS ; ! 150: pthr->fAutoSelectDims = global.pThrTop->fAutoSelectDims ; ! 151: pthr->fClearOnRedraw = global.pThrTop->fClearOnRedraw ; ! 152: pthr->fAutoStartRedraw = global.pThrTop->fAutoStartRedraw ; ! 153: pthr->fCollectBounds = global.pThrTop->fCollectBounds ; ! 154: ! 155: pthr->fFracRedraw = global.pThrTop->fFracRedraw ; ! 156: pthr->fPrimRedraw = global.pThrTop->fPrimRedraw ; ! 157: pthr->fAttrRedraw = global.pThrTop->fAttrRedraw ; ! 158: ! 159: pthr->lb = global.pThrTop->lb ; ! 160: pthr->flLineAttrs = LFA_LINEALL ; ! 161: pthr->mb = global.pThrTop->mb ; ! 162: pthr->flMarkerAttrs = LFA_MARKALL ; ! 163: pthr->ab = global.pThrTop->ab ; ! 164: pthr->flAreaAttrs = LFA_AREAALL ; ! 165: pthr->ib = global.pThrTop->ib ; ! 166: pthr->flImageAttrs = LFA_IMAGEALL ; ! 167: ! 168: pthr->usCurPrim = global.pThrTop->usCurPrim ; ! 169: pthr->usCurXform = global.pThrTop->usCurXform ; ! 170: pthr->usRecursion = global.pThrTop->usRecursion ; ! 171: pthr->usPolygonSides = global.pThrTop->usPolygonSides ; ! 172: pthr->cptMax = global.pThrTop->cptMax ; ! 173: pthr->dblXOff = global.pThrTop->dblXOff ; ! 174: pthr->dblYOff = global.pThrTop->dblYOff ; ! 175: pthr->dblXScale = global.pThrTop->dblXScale ; ! 176: pthr->dblYScale = global.pThrTop->dblYScale ; ! 177: pthr->dblRotation = global.pThrTop->dblRotation ; ! 178: pthr->flMiscAttrs = LFA_MISCALL ; ! 179: } ! 180: else ! 181: { ! 182: pthr->cPlanes = global.bm.cPlanes; ! 183: pthr->cBitCount = global.bm.cBitCount; ! 184: ! 185: pthr->cxWCS = 10000L; ! 186: pthr->cyWCS = 10000L; ! 187: ! 188: pthr->fAutoSizePS = TRUE; ! 189: pthr->fAutoSelectDims = TRUE; ! 190: pthr->fClearOnRedraw = TRUE; ! 191: pthr->fAutoStartRedraw = FALSE; ! 192: pthr->fCollectBounds = TRUE; ! 193: ! 194: pthr->fFracRedraw = TRUE; ! 195: pthr->fPrimRedraw = TRUE; ! 196: pthr->fAttrRedraw = TRUE; ! 197: ! 198: pthr->lb.lColor = CLR_NEUTRAL; ! 199: pthr->lb.usMixMode = FM_OVERPAINT; ! 200: pthr->lb.fxWidth = LINEWIDTH_NORMAL; ! 201: ; pthr->lb.lGeomWidth = 1L; ! 202: pthr->lb.usType = LINETYPE_SOLID; ! 203: ; pthr->lb.usEnd = LINEEND_FLAT; ! 204: ; pthr->lb.usJoin = LINEJOIN_BEVEL; ! 205: pthr->flLineAttrs = LFA_LINEALL; ! 206: ! 207: pthr->mb.lColor = CLR_NEUTRAL; ! 208: pthr->mb.lBackColor = CLR_BACKGROUND; ! 209: pthr->mb.usMixMode = FM_OVERPAINT; ! 210: pthr->mb.usBackMixMode = BM_LEAVEALONE; ! 211: pthr->mb.usSet = LCID_DEFAULT; ! 212: pthr->mb.usSymbol = MARKSYM_DIAMOND; ! 213: ; pthr->mb.sizfxCell.cx = 0L; ! 214: ; pthr->mb.sizfxCell.cy = 0L; ! 215: pthr->flMarkerAttrs = LFA_MARKALL; ! 216: ! 217: pthr->ab.lColor = CLR_NEUTRAL; ! 218: pthr->ab.lBackColor = CLR_BACKGROUND; ! 219: pthr->ab.usMixMode = FM_OVERPAINT; ! 220: pthr->ab.usBackMixMode = BM_OVERPAINT; ! 221: pthr->ab.usSet = LCID_DEFAULT; ! 222: pthr->ab.usSymbol = PATSYM_NOSHADE; ! 223: ; pthr->ab.ptlRefPoint.x = 0L; ! 224: ; pthr->ab.ptlRefPoint.y = 0L; ! 225: pthr->flAreaAttrs = LFA_AREAALL; ! 226: ! 227: pthr->ib.lColor = CLR_NEUTRAL; ! 228: pthr->ib.lBackColor = CLR_BACKGROUND; ! 229: pthr->ib.usMixMode = FM_OVERPAINT; ! 230: pthr->ib.usBackMixMode = FM_OVERPAINT; ! 231: pthr->flImageAttrs = LFA_IMAGEALL; ! 232: ! 233: pthr->usCurPrim = IDM_POLYLINE; ! 234: pthr->usCurXform = IDM_SAWTOOTH; ! 235: pthr->usRecursion = 1; ! 236: pthr->usPolygonSides = 3; ! 237: pthr->cptMax = MAX_POINT_COUNT; ! 238: pthr->dblXOff = 0.125; ! 239: pthr->dblYOff = 0.5; ! 240: pthr->dblXScale = 0.75; ! 241: pthr->dblYScale = 0.75; ! 242: pthr->dblRotation = 0.0; ! 243: pthr->flMiscAttrs = LFA_MISCALL; ! 244: } ! 245: ! 246: } ! 247: ! 248: ! 249: ! 250: ! 251: /************************************************************************ ! 252: * ! 253: * LfPostInitThread ! 254: * ! 255: * Initialize various values in the thread structure which required ! 256: * that a PS/DC/BM had been created. If thread inheritance is enabled, ! 257: * then copy as much as possible from the top thread, if there is ! 258: * one. ! 259: * ! 260: ************************************************************************/ ! 261: ! 262: VOID ! 263: LfPostInitThread(pthr) ! 264: PTHR pthr; ! 265: { ! 266: if (!(global.fThreadInheritance && global.pThrTop)) ! 267: { ! 268: pthr->lb.lGeomWidth = GpiQueryLineWidthGeom(pthr->hps); ! 269: pthr->lb.usEnd = (USHORT) GpiQueryLineEnd(pthr->hps); ! 270: pthr->lb.usJoin = (USHORT) GpiQueryLineJoin(pthr->hps); ! 271: ! 272: DevQueryCaps(pthr->hdc, CAPS_MARKER_WIDTH, 1L, (PLONG)&(pthr->mb.sizfxCell.cx)); ! 273: DevQueryCaps(pthr->hdc, CAPS_MARKER_HEIGHT, 1L, (PLONG)&(pthr->mb.sizfxCell.cy)); ! 274: ! 275: GpiQueryPatternRefPoint(pthr->hps,&(pthr->ab.ptlRefPoint)); ! 276: } ! 277: } ! 278: ! 279: ! 280: ! 281: ! 282: /************************************************************************ ! 283: * ! 284: * LfKillThread ! 285: * ! 286: * Force the given thread to die and release its resources. ! 287: * ! 288: ************************************************************************/ ! 289: ! 290: VOID ! 291: LfKillThread(pthr) ! 292: PTHR pthr; ! 293: { ! 294: int i, j; ! 295: ! 296: ! 297: /* This does not do anything if there aren't any threads. */ ! 298: ! 299: if (global.cThr && pthr) ! 300: { ! 301: /**************************************************************** ! 302: * Tell the thread to die when it can. ! 303: * If blocked on lSemRedraw, then it will recognize fTimeToDie ! 304: * as soon as it's unblocked. If it's currently drawing, ! 305: * it will recognize fInterrupted, kick out of the recursion, ! 306: * loop back up to check lSemRedraw, which will be clear, so ! 307: * it'll do as already mentioned. Set the priority to time- ! 308: * critical to speed things up. ! 309: ****************************************************************/ ! 310: ! 311: pthr->fTimeToDie = TRUE; ! 312: pthr->fInterrupted = TRUE; ! 313: DosSetPrty(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, pthr->tid); ! 314: DosSemClear(&pthr->lSemRedraw); ! 315: ! 316: ! 317: /**************************************************************** ! 318: * Once it's decided it must die, it will clean up after ! 319: * itself and exit quietly. To detect when it has actually ! 320: * exited, so that we can safely free up the stack, we will ! 321: * loop asking for the thread's priority until an error occurs. ! 322: * We will assume that an error implies the thread has exited. ! 323: ****************************************************************/ ! 324: ! 325: { ! 326: USHORT usT; ! 327: USHORT usRet; ! 328: while (!(usRet = DosGetPrty(PRTYS_THREAD, &usT, pthr->tid))); ! 329: if (usRet != ERROR_INVALID_THREADID) ! 330: { ! 331: MyMessageBox(global.hwnd, ! 332: "Cannot kill thread"); ! 333: return; ! 334: } ! 335: } ! 336: ! 337: ! 338: /**************************************************************** ! 339: * Extract the given thread from the group. This is done ! 340: * inside a critical section because the drawing threads ! 341: * call LfIsThreadTop, which reads global.aThr. ! 342: ****************************************************************/ ! 343: ! 344: i = 0; ! 345: while ((i < global.cThr) && (pthr != global.aThr[i])) ! 346: ++i; /* if i == global.cThr we have a problem */ ! 347: DosEnterCritSec(); ! 348: for (j = i; j < global.cThr-1; ++j) ! 349: global.aThr[j] = global.aThr[j+1]; ! 350: global.aThr[j] = NULL; /* clear out all copies of pthr */ ! 351: --global.cThr; ! 352: DosExitCritSec(); ! 353: ! 354: ! 355: /**************************************************************** ! 356: * Free up resources allocated for the thread. ! 357: ****************************************************************/ ! 358: ! 359: LfDeletePS(pthr); ! 360: DosFreeSeg(pthr->selStack); ! 361: DosFreeSeg(*(((PUSHORT)&pthr)+1)); ! 362: } ! 363: } ! 364: ! 365: ! 366: ! 367: ! 368: /************************************************************************ ! 369: * ! 370: * LfBringThreadToTop ! 371: * ! 372: * Bring the specified thread to the top, and invalidate the window ! 373: * to force a WM_PAINT message to make the thread's image visible. ! 374: * The given thread can be NULL, in which case just set pThrTop to ! 375: * NULL. ! 376: * ! 377: ************************************************************************/ ! 378: ! 379: VOID ! 380: LfBringThreadToTop(pthr) ! 381: PTHR pthr; ! 382: { ! 383: int i; ! 384: ! 385: ! 386: /******************************************************************** ! 387: * Find the given thread in the group. ! 388: ********************************************************************/ ! 389: ! 390: if (pthr) ! 391: { ! 392: i = 0; ! 393: while ((i < global.cThr) && (pthr != global.aThr[i])) ! 394: ++i; /* if i == global.cThr, we have problems */ ! 395: } ! 396: else ! 397: i = 32767; /* should cause gp fault if used */ ! 398: ! 399: ! 400: /******************************************************************** ! 401: * If the user wants the menu items updated, and we're switching ! 402: * away from an active thread, then uncheck the current thread's ! 403: * settings. ! 404: ********************************************************************/ ! 405: ! 406: if (global.fUpdateMenusOnThreadSwitch) ! 407: { ! 408: if (global.pThrTop) ! 409: { ! 410: UNCHECK_MENU_ITEM(global.hwndFrame, IDM_AUTORESIZE); ! 411: UNCHECK_MENU_ITEM(global.hwndFrame, IDM_AUTOSELECTDIMS); ! 412: UNCHECK_MENU_ITEM(global.hwndFrame, IDM_CLEARONREDRAW); ! 413: UNCHECK_MENU_ITEM(global.hwndFrame, IDM_AUTOSTARTREDRAW); ! 414: UNCHECK_MENU_ITEM(global.hwndFrame, IDM_COLLECTBOUNDS); ! 415: UNCHECK_MENU_ITEM(global.hwndFrame, IDM_FRACREDRAW); ! 416: UNCHECK_MENU_ITEM(global.hwndFrame, IDM_PRIMREDRAW); ! 417: UNCHECK_MENU_ITEM(global.hwndFrame, IDM_ATTRREDRAW); ! 418: UNCHECK_MENU_ITEM(global.hwndFrame, global.pThrTop->usCurPrim); ! 419: UNCHECK_MENU_ITEM(global.hwndFrame, global.pThrTop->usCurXform); ! 420: UNCHECK_MENU_ITEM(global.hwndFrame, global.pThrTop->dcType); ! 421: } ! 422: } ! 423: ! 424: ! 425: /******************************************************************** ! 426: * Switch the given thread to the top. ! 427: ********************************************************************/ ! 428: ! 429: DosEnterCritSec(); ! 430: global.iThrTop = i; ! 431: global.pThrTop = pthr; ! 432: DosExitCritSec(); ! 433: ! 434: ! 435: /******************************************************************** ! 436: * If we switched in a living thread, then invalidate the entire ! 437: * window. This will cause a WM_PAINT message to be sent, which ! 438: * will display the image from the new top thread. If the user ! 439: * has not disabled updating of the menus, then do that. ! 440: ********************************************************************/ ! 441: ! 442: if (pthr) ! 443: { ! 444: WinInvalidateRect(global.hwnd, NULL, FALSE); ! 445: ! 446: /* If the user wants menu items updated, then do it now. */ ! 447: if (global.fUpdateMenusOnThreadSwitch) ! 448: { ! 449: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_AUTORESIZE, pthr->fAutoSizePS); ! 450: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_AUTOSELECTDIMS, pthr->fAutoSelectDims); ! 451: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_CLEARONREDRAW, pthr->fClearOnRedraw); ! 452: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_AUTOSTARTREDRAW, pthr->fAutoStartRedraw); ! 453: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_COLLECTBOUNDS, pthr->fCollectBounds); ! 454: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_FRACREDRAW, pthr->fFracRedraw); ! 455: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_PRIMREDRAW, pthr->fPrimRedraw); ! 456: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_ATTRREDRAW, pthr->fAttrRedraw); ! 457: CHECK_MENU_ITEM (global.hwndFrame, pthr->usCurPrim); ! 458: CHECK_MENU_ITEM (global.hwndFrame, pthr->usCurXform); ! 459: CHECK_MENU_ITEM (global.hwndFrame, pthr->dcType); ! 460: ! 461: LfUpdateThreadMenu(); ! 462: } ! 463: } ! 464: } ! 465: ! 466: ! 467: ! 468: ! 469: /************************************************************************ ! 470: * ! 471: * LfIsThreadTop ! 472: * ! 473: * Returns TRUE if the given thread is the top one. Putting this ! 474: * test in a function isolates it and makes it easier to maintain ! 475: * a critical section. ! 476: * ! 477: ************************************************************************/ ! 478: ! 479: BOOL ! 480: LfIsThreadTop(pthr) ! 481: PTHR pthr; ! 482: { ! 483: BOOL f; ! 484: ! 485: f = FALSE; ! 486: DosEnterCritSec(); ! 487: if (pthr == global.pThrTop) ! 488: f = TRUE; ! 489: DosExitCritSec(); ! 490: ! 491: return f; ! 492: } ! 493: ! 494: ! 495: ! 496: ! 497: /************************************************************************ ! 498: * ! 499: * LfUpdateThreadMenu ! 500: * ! 501: * Brings the "Thread Bring thread to top" submenu in line with the ! 502: * currently active threads. ! 503: * ! 504: ************************************************************************/ ! 505: ! 506: VOID ! 507: LfUpdateThreadMenu() ! 508: { ! 509: /* ! 510: * Enable the numbers for threads that do exist. ! 511: * Disable the numbers for threads that don't exist. ! 512: * Uncheck everything, then check the right one. ! 513: */ ! 514: ! 515: int i; ! 516: ! 517: for (i = 0; i < global.cThr; ++i) ! 518: { ! 519: UNCHECK_MENU_ITEM(global.hwndFrame, IDM_THR0TOTOP+i); ! 520: ENABLE_MENU_ITEM (global.hwndFrame, IDM_THR0TOTOP+i); ! 521: } ! 522: ! 523: for ( ; i < MAX_THREADS; ++i) ! 524: { ! 525: UNCHECK_MENU_ITEM(global.hwndFrame, IDM_THR0TOTOP+i); ! 526: DISABLE_MENU_ITEM(global.hwndFrame, IDM_THR0TOTOP+i); ! 527: } ! 528: ! 529: CHECK_MENU_ITEM(global.hwndFrame, IDM_THR0TOTOP + global.iThrTop); ! 530: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.