Annotation of pmsdk/samples/linefrac/lfthread.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.