home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / text_cla / wfl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-12  |  18.5 KB  |  941 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Module Name:   wfl.cpp
  4. // 
  5. // Description:   Demonstration of workflow management system.
  6. //                Built on top of the link-list and binary tree algorithms.
  7. //
  8. // Written by:  John Tal
  9. //
  10. //
  11. // Modification History:
  12. //
  13. // Date          Programmer      Mod#     Modification
  14. // ---------------------------------------------------------------------------
  15. // 03-JUL-1991   J. Tal          V1.0-000 New
  16. //
  17. //
  18. //
  19.  
  20. #include <iostream.h>
  21. #include <string.h>
  22.  
  23.  
  24. #include "cmemlib.h"
  25.  
  26. #include "wfl.h"
  27.  
  28.  
  29.  
  30. //
  31. //  CompareState       used for SHORT to node comparison of short ids
  32. //                     by search routines
  33. //
  34.  
  35. SHORT CompareState(PVOID pvData1,PVOID pvData2)
  36. {
  37.  
  38.    PSHORT psState1;
  39.    PSHORT psState2;
  40.    WORK_ITEM_P  pstWorkItem;     
  41.    LLIST_CP  pclList;
  42.  
  43.  
  44.    psState1 = (PSHORT) pvData1;    // get direct state in short
  45.  
  46.    pclList = (LLIST_CP) pvData2;   // ptr to list class
  47.  
  48.    pclList -> FindFirst((PPVOID) &pstWorkItem);  // get first object/item in list class
  49.  
  50.    psState2 = &(pstWorkItem -> sState);  // get state
  51.  
  52.    if(*psState1 == *psState2)
  53.       return(0);
  54.    else if(*psState1 > *psState2)
  55.       return(-1);
  56.    else
  57.       return(1);
  58.  
  59. }
  60.  
  61. //
  62. //   May want to make function more sophisticated in future, now just
  63. //   takes first one
  64. //
  65.  
  66.  
  67. SHORT PROFILE_C::Get(PROFILE_PP ppclProfile)
  68. {
  69.    C_DEF_MODULE("PROFILE_C::Get")
  70.  
  71.  
  72.    C_STATUS = clProfiles.FindFirst((PPVOID) ppclProfile);
  73.  
  74.    C_RETURN
  75. }
  76.                               
  77.  
  78.  
  79. //
  80. //  CompareNodeState   used for node to node comparison of short ids
  81. //                     by delete routines
  82. //
  83.  
  84. SHORT CompareNodeState(PVOID pvData1,PVOID pvData2)
  85. {
  86.    PSHORT psState1;
  87.    PSHORT psState2;
  88.   
  89.    LLIST_CP  pclList1;
  90.    LLIST_CP  pclList2;
  91.  
  92.    WORK_ITEM_P pstWorkItem1;
  93.    WORK_ITEM_P pstWorkItem2;
  94.  
  95.  
  96.    pclList1 = (LLIST_CP) pvData1;     // class is at this ptr
  97.  
  98.    pclList1 -> FindFirst((PPVOID) &pstWorkItem1);  // get first object/item in list class
  99.    
  100.    psState1 = &(pstWorkItem1 -> sState);   // ptr to state
  101.  
  102.  
  103.  
  104.    pclList2 = (LLIST_CP) pvData2;     // class of link list at this ptr
  105.    
  106.    pclList2 -> FindFirst((PPVOID) &pstWorkItem2);  // get first object/item in list class
  107.    
  108.    psState1 = &(pstWorkItem2 -> sState);  // ptr to state
  109.  
  110.  
  111.  
  112.    if(*psState1 == *psState2)
  113.       return(0);
  114.    else if(*psState1 > *psState2)
  115.       return(-1);
  116.    else
  117.       return(1);
  118.  
  119. }
  120.  
  121. //
  122. //  CompareIdNode
  123. //
  124.  
  125.  
  126. SHORT CompareIdNode(PVOID pvData1,PVOID pvData2)
  127. {
  128.    PCHAR  pcId1;
  129.    PCHAR  pcId2;
  130.  
  131.    pcId1 = (PCHAR) pvData1;
  132.    pcId2 = (PCHAR) pvData2;
  133.  
  134.    return(strcmp(pcId1,pcId2));
  135. }
  136.  
  137.  
  138. //
  139. //  WrkProAdd
  140. //
  141. //  Adds a profile for a process to the process' profile list
  142. //
  143.  
  144. SHORT PROFILE_C::Add(PROFILE_P pstAProfile)
  145. {
  146.    C_DEF_MODULE("WrkProAdd")
  147.  
  148.    PROFILE_P  pstProfile;
  149.    PVOID      pvData;
  150.  
  151.  
  152.    pstProfile = new PROFILE_T;
  153.  
  154.    memcpy(pstProfile,pstAProfile,sizeof(PROFILE_T));
  155.  
  156.  
  157.    C_STATUS = clProfiles.FindLast(&pvData);
  158.  
  159.    C_STATUS = clProfiles.AddAfterCur((PVOID) pstProfile);
  160.  
  161.    C_RETURN
  162. }
  163.  
  164.  
  165. //
  166. //  Add another job.
  167. //  Each workflow_T is in a linked-list off of a single binary tree node
  168. //
  169.  
  170. SHORT
  171. WORK_FLOW_C::Add(PCHAR szId, SHORT sState, PVOID pvData)
  172. {
  173.    C_DEF_MODULE("WORK_FLOW_C::Add")
  174.  
  175.    PVOID pvData1;
  176.    PVOID pvData2;
  177.    LLIST_CP  pclLlist;
  178.    WORK_ITEM_P pstWorkItem;
  179.  
  180.    pstWorkItem = new WORK_ITEM_T;
  181.  
  182.  
  183.    //
  184.    //  Check if in Id Tree, if so, is error
  185.    //
  186.  
  187.    C_STATUS = clIdTree.SetCompareFunc(CompareIdNode);
  188.  
  189.    C_STATUS = clIdTree.Find((PVOID) szId,&pvData1);   // fix 16-Feb-92 was pvData
  190.  
  191.    if(pvData1 != NULL)    // fix 16-Feb-92 was pvData
  192.    {
  193.       C_LEAVE(WRK_DUPLICATE_ID)
  194.    }
  195.  
  196.  
  197.    //
  198.    //  Add to Id Tree
  199.    //
  200.  
  201.    C_STATUS = clIdTree.Insert((PVOID) szId);
  202.  
  203.    //
  204.    // Populate new item
  205.    //
  206.  
  207.    pstWorkItem -> sState = sState;
  208.    strcpy(pstWorkItem -> szId, szId);
  209.    pstWorkItem -> fLocked = C_FALSE;
  210.    pstWorkItem -> pvData = pvData;
  211.  
  212.  
  213.    C_STATUS = clStateTree.SetCompareFunc(CompareNodeState);
  214.  
  215.    C_STATUS = clStateTree.Find((PVOID) &sState,(PPVOID) &pvData1);
  216.  
  217.    if(pvData1 == NULL)
  218.    {
  219.  
  220. #if DEBUG
  221.    cout << "WrkJobAdd:   Adding entry for state " << pstWorkItem -> sState << "\n";
  222. #endif
  223.  
  224.       //
  225.       //  Must add entry for this state
  226.       //
  227.  
  228.       pclLlist = new (LLIST_C);
  229.  
  230.       //
  231.       //  Put info on Work Item into link list
  232.       //
  233.  
  234.       pclLlist -> Insert((PVOID) pstWorkItem);
  235.               
  236.       //
  237.       //  Put info on Link List into Tree
  238.       //
  239.  
  240.       C_STATUS = clStateTree.Insert((PVOID) pclLlist);
  241.  
  242.    }
  243.    else
  244.    {
  245. #if DEBUG
  246.    cout << "WrkJobAdd:   Appending entry for state " << pstWorkItem -> sState << "\n";
  247. #endif
  248.  
  249.       //
  250.       //  Find current llist 
  251.       //
  252.  
  253.       pclLlist = (LLIST_CP) pvData1;
  254.  
  255.       //
  256.       //  Find last one of current list
  257.       //
  258.  
  259.       C_STATUS = pclLlist -> FindLast((PPVOID) pvData2);
  260.  
  261.       //
  262.       //  Add new one after current last one
  263.       //  Maintains FIFO ordering
  264.       //
  265.  
  266.       C_STATUS = pclLlist -> AddAfterCur((PVOID) pstWorkItem); 
  267.    }
  268.  
  269. C_MODULE_EXIT:
  270.  
  271.    C_RETURN
  272. }
  273.  
  274.  
  275.  
  276.  
  277. //
  278. //  WrkJobSelect, select a job to work on
  279. //  Automatically locks a job when selected
  280. //
  281.  
  282. SHORT WORK_FLOW_C::Select(PROFILE_CP pclProfile, PCHAR * ppcId, PVOID * ppvData)
  283. {
  284.    C_DEF_MODULE("WORK_FLOW::Select")
  285.  
  286.    WORK_ITEM_P pstWorkItem;
  287.    PROFILE_P   pstProfile;
  288.    BOOL        fFoundJob = C_FALSE;
  289.    LLIST_CP    pclStateList;
  290.  
  291.    *ppvData = NULL;
  292.  
  293.  
  294.    
  295.    C_STATUS = pclProfile -> Get(&pstProfile);
  296.  
  297.    //
  298.    //  Check all jobs based on jobs which this process can process
  299.    //
  300.  
  301.    C_STATUS = clStateTree.SetCompareFunc(CompareState);
  302.  
  303.  
  304.    while(!C_STATUS && (pstProfile != NULL) && !fFoundJob)
  305.    {
  306.        C_STATUS = clStateTree.Find((PVOID) 
  307.                                     &(pstProfile -> sTrnState[WRK_SEL_STATE]),
  308.                                    (PPVOID) &pclStateList);
  309.  
  310.        if(pclStateList == NULL)
  311.       break;
  312.  
  313.        if(pclStateList != NULL && !fFoundJob)
  314.        {
  315.           //
  316.           //  Found 1 or more jobs at this state
  317.           //
  318.           //  Check each member in linked list till no more or got one
  319.           //
  320.  
  321.           C_STATUS = pclStateList -> FindFirst((PPVOID) &pstWorkItem);
  322.  
  323.           while(pstWorkItem != NULL && !fFoundJob)
  324.           {
  325.              if(!pstWorkItem -> fLocked)
  326.              {
  327.  
  328.                 //
  329.                 //  Mark job as locked, we are new owners
  330.                 //
  331.  
  332.                 pstWorkItem -> fLocked = C_TRUE;
  333.  
  334.         strcpy(pstWorkItem -> szKey, pstProfile -> szKey);
  335.  
  336.         *ppcId = pstWorkItem -> szId;
  337.  
  338.         *ppvData = pstWorkItem -> pvData;
  339.  
  340.                 fFoundJob = C_TRUE;
  341.  
  342.              }
  343.  
  344.              //
  345.              //  If still looking, check next job
  346.              //
  347.  
  348.          if(!fFoundJob)
  349.          {
  350.         C_STATUS = pclStateList -> GetNext((PPVOID) &pstWorkItem);
  351.         if(C_STATUS)
  352.            break;
  353.          } 
  354.       }
  355.  
  356.        } 
  357.  
  358.        //  
  359.        //  If still looking, check next profile
  360.        //
  361.  
  362.        //if((pclStateList == NULL) && !fFoundJob)
  363.        // C_STATUS = pclProfile -> Get(&pstProfile);
  364.    }
  365.  
  366.    if(!fFoundJob)
  367.       C_SET_STATUS(WRK_NO_JOB);
  368.  
  369.    C_RETURN
  370.  
  371. }
  372.  
  373.  
  374. //
  375. //  WrkJobTrans
  376. //
  377. //  Set the job to the appropriate transition state
  378. //  and unlocks job if told to
  379. //
  380.  
  381. SHORT WORK_FLOW_C::SetTrans(PCHAR szId, PROFILE_CP pclProfile, SHORT sTrnStateNdx)
  382. {
  383.    C_DEF_MODULE("WORK_FLOW_C::SetTrans")
  384.  
  385.    SHORT sSaveState;
  386.    WORK_ITEM_P  pstWorkItem;
  387.    PVOID pvData;
  388.    PROFILE_P    pstProfile;
  389.    BOOL   fFoundJob;
  390.    LLIST_CP   pclStateList;
  391.  
  392. #if DEBUG
  393.    cout << "WrkJobTrans: Setting " << szId << " to state ndx " << sTrnStateNdx << "\n";
  394. #endif
  395.  
  396. #ifdef WHY
  397.  
  398.    //
  399.    //  Get WORK_ITEM based on szId
  400.    //
  401.  
  402.    C_STATUS = clIdTree.SetCompareFunc(CompareIdNode);
  403.  
  404.    C_STATUS = clIdTree.Find((PVOID) szId, (PPVOID)&pstWorkItem);
  405.  
  406.  
  407.    //
  408.    //  Must also unlink from link list in workflow tree
  409.    //  and add to new link list
  410.    //
  411.  
  412. #endif
  413.  
  414.  
  415.  
  416.    C_STATUS = pclProfile -> Get(&pstProfile);
  417.  
  418.    sSaveState = pstProfile -> sTrnState[sTrnStateNdx];
  419.  
  420.  
  421.  
  422.    C_STATUS = clStateTree.SetCompareFunc(CompareState);
  423.  
  424.    while(!C_STATUS && (pstProfile != NULL) && !fFoundJob)
  425.    {
  426.        C_STATUS = clStateTree.Find((PVOID)
  427.                                     &(pstProfile -> sTrnState[WRK_SEL_STATE]),
  428.                                    (PPVOID) &pclStateList);
  429.  
  430.        if(pclStateList != NULL && !fFoundJob)
  431.        {
  432.           //
  433.           //  Found 1 or more jobs at this state
  434.           //
  435.           //  Check each member in linked list till no more or got one
  436.           //
  437.  
  438.           C_STATUS = pclStateList -> FindFirst((PPVOID) &pstWorkItem);
  439.  
  440.           while(pstWorkItem != NULL && !fFoundJob)
  441.           {
  442.  
  443.              //
  444.              //  All same states, check if match on owner
  445.              //
  446.  
  447.          if(strcmp(pstWorkItem -> szKey,pstProfile -> szKey) == 0)
  448.              {
  449.  
  450.                  //
  451.                  //  Found it, delete from old list, add to new/current one
  452.                  //
  453.  
  454.                  fFoundJob = C_TRUE;
  455.  
  456.          C_STATUS = pclStateList -> DeleteCur();
  457.  
  458.          C_STATUS = pclStateList -> FindFirst((PPVOID) & pvData);
  459.  
  460.                  if(pvData == NULL)
  461.                  {
  462.  
  463.                     //
  464.                     //  Delete tree entry because no more at this state
  465.                     //
  466.  
  467.                     C_STATUS = clStateTree.Delete((PVOID) &sSaveState);
  468. #if DEBUG
  469.             cout << "WORK_FLOW_C::Trans: Deleting state " << sSaveState << "\n";
  470. #endif
  471.  
  472.         }
  473.         else
  474.         {
  475. #if DEBUG
  476.             cout << "WrkJobTrans: Resetting node for state " << sSaveState << "\n";
  477. #endif
  478.         }
  479.  
  480.         //
  481.         //  Add to new/current list
  482.         //
  483.  
  484.         C_STATUS = pclProfile -> Get(&pstProfile);
  485.  
  486.         pstWorkItem -> sState = pstProfile -> sTrnState[sTrnStateNdx];
  487.  
  488.  
  489.         C_STATUS = Add(szId,pstWorkItem -> sState,(PVOID) pstWorkItem);
  490.  
  491.       }
  492.  
  493.       C_STATUS = pclStateList -> GetNext((PPVOID) &pstWorkItem);
  494.  
  495.        }
  496.  
  497.     }
  498.  
  499.   }
  500.  
  501.  
  502.   C_RETURN 
  503.  
  504. }
  505.  
  506.  
  507.  
  508. //
  509. //
  510. //
  511.  
  512.  
  513. SHORT WORK_FLOW_C::UnLock(PCHAR pcId, PROFILE_CP pclProfile)
  514. {
  515.    C_DEF_MODULE("WORK_FLOW_C::UnLock")
  516.  
  517.    PVOID  pvData;
  518.    BOOL   fFoundJob = C_FALSE;
  519.    SHORT  sCnt;
  520.    WORK_ITEM_P  pstWorkItem;
  521.    PROFILE_P    pstProfile;
  522.  
  523.    LLIST_CP   pclStateList;
  524.  
  525. #if 0
  526.  
  527.    //
  528.    //  Look in Id Tree
  529.    //
  530.  
  531.    C_STATUS = clIdTree.SetCompareFunc(CompareIdNode);
  532.  
  533.    C_STATUS = clIdTree.Find((PVOID) pcId,&pvData);
  534.  
  535.    if(pvData == NULL)
  536.    {
  537.       C_LEAVE(WRK_NO_JOB)
  538.    }
  539.  
  540.  
  541.    pclProfile -> Get(&pst
  542.    pstWorkItem = (WORK_ITEM_P) pvData;
  543.  
  544.    //
  545.    //  See if profiles have access to pcId
  546.    //
  547.    //  This is done by comparing pcId current state to selection or
  548.    //  activation state of profile
  549.    //
  550.  
  551.    pstProfile = NULL;
  552.  
  553.    C_STATUS = pclProfile -> Get(&pstProfile);
  554.  
  555.    while(!C_STATUS && (pstProfile != NULL) && !fFoundJob)
  556.    {
  557.  
  558.        for(sCnt = 0; sCnt < pstProfile -> sTrnStates; sCnt++)
  559.            if(pstWorkItem -> sState == pstProfile -> sTrnState[sCnt])
  560.            {
  561.               fTrnOk = C_TRUE;
  562.               break;
  563.            }
  564.  
  565.        if(
  566.           (fTrnOk)
  567.           &&
  568.           (pstWorkItem -> fLocked)
  569.           &&
  570.           (strcmp(pstWorkItem -> szKey,pstProfile -> szKey) == 0)
  571.          )
  572.        {
  573.            pstWorkItem -> fLocked = C_FALSE;
  574.            fFoundJob = C_TRUE;
  575.        }
  576.  
  577.  
  578.    }
  579.  
  580.  
  581.    C_MODULE_EXIT:
  582.  
  583.    C_RETURN
  584.  
  585. #endif
  586.  
  587.    
  588.    C_STATUS = pclProfile -> Get(&pstProfile);
  589.  
  590.    //
  591.    //  Check all jobs based on jobs which this process can process
  592.    //
  593.  
  594.    C_STATUS = clStateTree.SetCompareFunc(CompareState);
  595.  
  596.  
  597.    while(!C_STATUS && (pstProfile != NULL) && !fFoundJob)
  598.    {
  599.        C_STATUS = clStateTree.Find((PVOID) 
  600.                     &(pstProfile -> sTrnState[WRK_ACT_STATE]),
  601.                                    (PPVOID) &pclStateList);
  602.  
  603.        if(pclStateList == NULL)
  604.       break;
  605.  
  606.        if(pclStateList != NULL && !fFoundJob)
  607.        {
  608.           //
  609.           //  Found 1 or more jobs at this state
  610.           //
  611.  
  612.           C_STATUS = pclStateList -> FindFirst((PPVOID) &pstWorkItem);
  613.  
  614.           while(pstWorkItem != NULL && !fFoundJob)
  615.           {
  616.              if(pstWorkItem -> fLocked)
  617.              {
  618.  
  619.                 //
  620.                 //  Mark job as locked, we are new owners
  621.                 //
  622.  
  623.                 pstWorkItem -> fLocked = C_TRUE;
  624.  
  625.                 fFoundJob = C_TRUE;
  626.  
  627.              }
  628.  
  629.              //
  630.              //  If still looking, check next job
  631.              //
  632.  
  633.          if(!fFoundJob)
  634.          {
  635.         C_STATUS = pclStateList -> GetNext((PPVOID) &pstWorkItem);
  636.         if(C_STATUS)
  637.            break;
  638.          } 
  639.       }
  640.  
  641.        } 
  642.  
  643.    }
  644.  
  645.    C_RETURN
  646.  
  647. }
  648.  
  649.  
  650. /////////////////////////////////////////////////////////////////////
  651. /////////////////////////////////////////////////////////////////////
  652. /////////////////////////////////////////////////////////////////////
  653.  
  654.  
  655. #define TEST 1
  656. #define DEBUG 1
  657.  
  658.  
  659.  
  660. #ifdef TEST
  661.  
  662. //
  663. //  Beginning of test program
  664. //
  665.  
  666.  
  667. struct JOB_S           // a dummy 'job' to process //
  668. {
  669.      SHORT sData1;
  670.      SHORT sData2;
  671. };
  672.  
  673. typedef struct JOB_S JOB_T;
  674. typedef JOB_T * JOB_P;
  675.  
  676.  
  677. JOB_T stJob1;    // some jobs //
  678. JOB_T stJob2;
  679. JOB_T stJob3;
  680. JOB_T stJob4;
  681.  
  682.  
  683. int  Process1();   // processes to process the jobs //
  684. int  Process2();
  685. int  Process3();
  686.  
  687.  
  688. int  (*Procs[3])() = { Process1, Process2, Process3 };  // array of processes //
  689.  
  690.  
  691. WORK_FLOW_C clWorkFlow;
  692.  
  693. PROFILE_C   clProfile1;
  694. PROFILE_C   clProfile2;
  695. PROFILE_C   clProfile3;
  696.  
  697. int  DoProcs();
  698.  
  699.  
  700.  
  701. main()
  702. {
  703.     C_DEF_MODULE("main")
  704.  
  705.     SHORT   s1,s2,s3,s4,s5,s6;
  706.  
  707.     PROFILE_T  stProfile;
  708.  
  709.     //
  710.     //  Initialize 'Job' data
  711.     //
  712.  
  713.     stJob1.sData1 = 0;         // 'bad data' , will get sent 1, to 2, to 1, to 3 //
  714.     stJob1.sData2 = 0;
  715.  
  716.     stJob2.sData1 = 1;
  717.     stJob2.sData2 = 1;
  718.  
  719.     stJob3.sData1 = 1;
  720.     stJob3.sData2 = 1;
  721.  
  722.     stJob4.sData1 = 1;
  723.     stJob4.sData2 = 1;
  724.  
  725.     //
  726.     //  Initialize data for each 'process'
  727.     //
  728.  
  729.     strcpy(stProfile.szKey,"PRE_PROC");
  730.     stProfile.sTrnStates = 5;
  731.     stProfile.sTrnState[0] = 100;  // Selection //
  732.     stProfile.sTrnState[1] = 101;  // Activation //
  733.     stProfile.sTrnState[2] = 300;  // successful completion //
  734.     stProfile.sTrnState[3] = 200;  // error 1 //
  735.     stProfile.sTrnState[4] = 250;  // error 2 //
  736.  
  737.     clProfile1.Add(&stProfile);
  738.  
  739.     strcpy(stProfile.szKey,"ERR_PROC");
  740.     stProfile.sTrnStates = 5;
  741.     stProfile.sTrnState[0] = 200;  // Selection //
  742.     stProfile.sTrnState[1] = 201;  // Activation //
  743.     stProfile.sTrnState[2] = 100;  // successful completion //
  744.     stProfile.sTrnState[3] = 999;  // error 1 //
  745.     stProfile.sTrnState[4] = 998;  // error 2 //     
  746.  
  747.     clProfile2.Add(&stProfile);
  748.  
  749.     strcpy(stProfile.szKey,"END_PROC");
  750.     stProfile.sTrnStates = 5;
  751.     stProfile.sTrnState[0] = 300;  // Selection //
  752.     stProfile.sTrnState[1] = 301;  // Activation //
  753.     stProfile.sTrnState[2] = 700;  // successful completion //
  754.     stProfile.sTrnState[3] = 970;  // error 1 //
  755.     stProfile.sTrnState[4] = 980;  // error 2 //     
  756.  
  757.     clProfile3.Add(&stProfile);
  758.  
  759.  
  760.     //
  761.     //  Initialize each job
  762.     //
  763.  
  764.  
  765.     clWorkFlow.Add("Job1",100,(PVOID) &stJob1);
  766.     clWorkFlow.Add("Job2",200,(PVOID) &stJob2);
  767.     clWorkFlow.Add("Job3",300,(PVOID) &stJob3);
  768.     clWorkFlow.Add("Job4",400,(PVOID) &stJob4);
  769.  
  770.     C_SET_STATUS(0);
  771.  
  772.     s1 = 1;   // remember results of last 5 process executions //
  773.     s2 = 0;
  774.     s3 = 0;
  775.     s4 = 0;
  776.     s5 = 0;
  777.     s6 = 0;
  778.  
  779.     do
  780.     {
  781.        s6 = s5;
  782.        s5 = s4;
  783.        s4 = s3;
  784.        s3 = s2; 
  785.        s2 = s1;
  786.  
  787.        C_STATUS = DoProcs();    //  simple 'multi-tasker' //
  788.  
  789.        if(!C_STATUS)
  790.           s1 = 1;
  791.        else
  792.           s1 = 0;
  793.  
  794.     } while( (s1+s2+s3+s4+s5+s6) > 0);
  795.  
  796.  
  797. }
  798.  
  799.  
  800. //
  801. //  'Multi-task' (round-robin) the different processes
  802. //
  803.  
  804. int DoProcs()
  805. {
  806.   C_DEF_MODULE("DoProcs")
  807.   
  808.   static SHORT sLastProc = 0;
  809.  
  810.   C_STATUS = Procs[sLastProc]();
  811.  
  812.   sLastProc++;
  813.  
  814.   if(sLastProc > 2)
  815.      sLastProc = 0;
  816.  
  817.   C_RETURN
  818.  
  819. }
  820.  
  821.  
  822. //
  823. //  Process 1
  824. //
  825.  
  826. int Process1()
  827. {
  828.    C_DEF_MODULE("Process 1")
  829.  
  830.    PCHAR   pcId;   
  831.    JOB_P   pstJob;
  832.  
  833.    cout << "Process 1 - Executing\n";
  834.  
  835.    C_STATUS = clWorkFlow.Select(&clProfile1,&pcId,(PPVOID) &pstJob);
  836.  
  837.    if(pstJob == NULL)
  838.    {
  839.      cout << "Process 1 - Found nothing to work on\n";
  840.      C_STATUS = -1;
  841.    }
  842.    else
  843.    {
  844.  
  845.      cout << "Process 1 - Working on job " << pcId << "\n";
  846.  
  847.      clWorkFlow.SetTrans(pcId,&clProfile1,WRK_ACT_STATE);
  848.  
  849.      if(pstJob -> sData1 == 0)
  850.      {
  851.     cout << "Process 1 - Incorrect Data on job " << pcId << "\n";
  852.  
  853.         clWorkFlow.UnLock(pcId,&clProfile1);
  854.         clWorkFlow.SetTrans(pcId,&clProfile1,WRK_TRN_STATE+WRK_TRN_ERR_1);
  855.      }
  856.      else
  857.      {
  858.     cout << "Process 1 - Completing job " << pcId << "\n";
  859.  
  860.         clWorkFlow.UnLock(pcId,&clProfile1);
  861.         clWorkFlow.SetTrans(pcId,&clProfile1,WRK_TRN_STATE+WRK_TRN_OK);
  862.      }
  863.    }
  864.  
  865.    C_RETURN
  866. }
  867.  
  868.  
  869. //
  870. //  Process 2, is sent 'bad' data by process 1 for correction if possible
  871. //
  872.  
  873. int Process2()
  874. {
  875.    C_DEF_MODULE("Process 2")
  876.  
  877.    JOB_P    pstJob;
  878.    PCHAR    pcId;
  879.  
  880.    cout << "\nProcess 2 - Executing\n";
  881.  
  882.  
  883.    C_STATUS = clWorkFlow.Select(&clProfile2,&pcId,(PPVOID) &pstJob);
  884.  
  885.    if(pstJob == NULL)
  886.    {
  887.      cout << "Process 2 - Found nothing to work on\n";
  888.      C_STATUS = -1;
  889.    }
  890.    else
  891.    {   
  892.  
  893.      cout << "Process 2 - Working on job " << pcId << "\n";
  894.  
  895.      clWorkFlow.SetTrans(pcId,&clProfile2,WRK_ACT_STATE);
  896.  
  897.      pstJob -> sData1 = 1;  // Correct problem which sent it here //
  898.  
  899.      cout << "Process 2 - Completing job " << pcId << "\n";
  900.  
  901.      clWorkFlow.SetTrans(pcId,&clProfile2,WRK_TRN_STATE+WRK_TRN_OK);
  902.  
  903.    } 
  904.  
  905.    C_RETURN
  906. }
  907.  
  908.  
  909. int Process3()
  910. {
  911.    C_DEF_MODULE("Process 3")
  912.  
  913.    JOB_P    pstJob;
  914.    PCHAR    pcId;
  915.  
  916.    cout << "\nProcess 3 - Executing\n";
  917.  
  918.    C_STATUS = clWorkFlow.Select(&clProfile3,&pcId,(PPVOID) &pstJob);
  919.  
  920.    if(pstJob == NULL)
  921.    {
  922.      cout << "Process 3 - Found nothing to work on\n";
  923.      C_STATUS = -1;
  924.    }
  925.    else
  926.    {   
  927.  
  928.      cout << "Process 3 - Working on job " << pcId << "\n";
  929.  
  930.      clWorkFlow.SetTrans(pcId,&clProfile3,WRK_ACT_STATE);
  931.  
  932.      clWorkFlow.UnLock(pcId,&clProfile3);
  933.      clWorkFlow.SetTrans(pcId,&clProfile3,WRK_TRN_STATE+WRK_TRN_OK);
  934.  
  935.    }
  936.  
  937.    C_RETURN
  938. }
  939.  
  940. #endif
  941.