/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        G E S T I O N   " I N T E R N E "   D U   P A R A L L E L I S M E  :                                                       */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xcg/parallele.1N$K' :                                                                                          */
/*                                                                                                                                   */
/*                    Jean-Francois COLONNA (LACTAMME, 20090414184411).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        I N T E R F A C E   ' listG '  :                                                                                           */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        :Debut_listG:                                                                                                              */
/*        :Fin_listG:                                                                                                                */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D I R E C T I V E S   S P E C I F I Q U E S   D E   C O M P I L A T I O N  :                                               */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
@define   PRAGMA_CL_____PAS_DE_LIBRAIRIES_DYNAMIQUES
                                        /* Plus prudent, a cause de 'v $xcg/FindExec.01$Z .xcg.parallele.1..X'...                    */
@define   PRAGMA_CL_____PAS_DE_FICHIER_____PARAM
                                        /* Introduit le 20170416092947 a cause de l'argument 'nombre_de_processus_parallelisables'   */
                                        /* qui est local a chaque MACHINE ('v $xcg/parallele.14$I ProcessorNumber')...               */

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        F I C H I E R S   D ' I N C L U D E S  :                                                                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#include  INCLUDES_MINI

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        P A R A M E T R E S  :                                                                                                     */
/*                                                                                                                                   */
/*===================================================================================================================================*/
#include  xcg/parallele.14.I"

#define   COMPATIBILITE_20120114                                                                                                        \
                    VRAI                                                                                                                \
                                        /* Permet de se placer dans l'etat anterieur a l'introduction des 'PRIORITE_DES_COMMANDES'.  */
                                        /* On notera que c'est l'etat par defaut et ceci a cause du fait qu'il y a de grosses        */
                                        /* differences entre 'LANCEMENT_D_UNE_COMMANDE_SOUS_SH_DE_BASE' et                           */
                                        /* 'LANCEMENT_D_UNE_COMMANDE_SOUS_SH' en ce qui concerne la disponibilite de 'nice', le      */
                                        /* comportement vis a vis des parentheses ou encore des quotes. Or cette commande est tres   */
                                        /* utilisee par exemple dans 'execRVB' ou encore dans 'v $xcg/FindExec.01$Z PPaRaLlElE'.     */
                                        /* Donc pour ne pas perturber tout cela, retour avant le 20120114181453...                   */

#define   BLOQUER_LE_PARALLELISME                                                                                                       \
                    FAUX                                                                                                                \
                                        /* La possibilite d'inhiber le parallelisme directement a ete introduite le 20100630192050   */ \
                                        /* pour 'v $Falias_execALBUM parallelisme='. Le 20100701095323, la logique de cet indicateur */ \
                                        /* a ete inversee en passant de 'AUTORISER_LE_PARALLELISME' a 'BLOQUER_LE_PARALLELISME'...   */

#define   AJUSTER_AUTOMATIQUEMENT_PCMemorySizeMB                                                                                        \
                    VRAI                                                                                                                \
                                        /* La variable d'environnement '$PCMemorySizeMB' sera par defaut reduite proportionnellement */ \
                                        /* a 'nombre_de_processus_parallelisables' (introduit le 20120214104603).                    */

#define   COMPATIBILITE_PARALLELE_14                                                                                                    \
                    VRAI                                                                                                                \
                                        /* La possibilite d'inhiber la compatibilite avec 'v $xcg/parallele.14$K' a ete introduite   */ \
                                        /* le 20090416105323...                                                                      */
#define   EN_MODE_COMPATIBILITE_PARALLELE_14_AVERTIR_S_IL_Y_A_TROP_DE_PROCESS                                                           \
                    VRAI                                                                                                                \
                                        /* La possibilite d'inhiber le message correspondant a ete introduite le 20100412134427...   */

#define   DUPLIQUER_N_FOIS_LA_COMMANDE                                                                                                  \
                    VRAI                                                                                                                \
                                        /* Faut-il dupliquer la commande autant de fois qu'il y a de processus paralleles possibles  */ \
                                        /* ('VRAI') ou pas ('FAUX') ? Cela fut introduit le 20140418122211. On notera qu'avant cette */ \
                                        /* date, tout se passait comme si cette option (absente alors) etait 'VRAI'. La valeur par   */ \
                                        /* defaut est devenue 'VRAI' le 20140419102659 afin d'assurer la compatibilite avec les tres */ \
                                        /* nombreux usages du type 'v $xiac/$Fnota .xcs.Linda.vv.Z''...                              */

#define   EXECUTER_LES_COMMANDES_SOUS_CSH                                                                                               \
                    FAUX                                                                                                                \
                                        /* La possibilite d'executer les commandes sous '$CSH' a ete introduite le 20091021093824,   */ \
                                        /* la valeur par defaut assurant la compatibilite anterieure...                              */

#define   PREMIER_NUMERO                                                                                                                \
                    UN
#define   NOMBRE_DE_CHIFFRES_A_EDITER                                                                                                   \
                    QUATRE
                                        /* Nombre de chiffres a editer pour les numeros (introduit le 20111116210724).               */

#define   CARACTERE_DE_SEPARATION_DES_COMMANDES                                                                                         \
                    K_DIESE                                                                                                             \
                                        /* Caractere de separation des commandes a paralleliser.                                     */ \
                                        /*                                                                                           */ \
                                        /* Le 20090415081248, 'K_POINT_VIRGULE' fut remplace par 'K_DIESE' a fin de faciliter        */ \
                                        /* l'usage de chaines de commandes separees par des ";"s et parallelisables...               */

#define   EDITER_LES_COMMANDES_AVANT_LEUR_LANCEMENT                                                                                     \
                    FAUX                                                                                                                \
                                        /* Afin de permettre d'editer les commandes au lancement (introduit le 20120114184627)...    */

#define   QUOTE_DES_COMMANDES                                                                                                           \
                    C_QUOTE                                                                                                             \
                                        /* Afin de pouvoir encadrer les commandes (introduit le 20120114190709)...                   */ \
                                        /*                                                                                           */ \
                                        /* Le 20120115111544 'C_VIDE' a ete remplace par 'C_QUOTE' a cause de "parentheser=VRAI"     */ \
                                        /* qui est utilise, par exemple, dans l'alias 'execRVB'. Or de toute evidence '$SH' utilise  */ \
                                        /* a partir de cette date dans 'v $xil/defi_c1$vv$DEF LANCEMENT_D_UNE_COMMANDE_SOUS_SH'      */ \
                                        /* ne tolere pas les parentheses si elles ne sont pas quotees...                             */

#define   PRIORITE_DES_COMMANDES                                                                                                        \
                    ZERO                                                                                                                \
                                        /* Priorite d'ordonnancement ("scheduling") des commandes (introduite le 20120114181453)...  */
#define   TEMPORISATION_APRES_CHAQUE_LANCEMENT                                                                                          \
                    ZERO                                                                                                                \
                                        /* La possibilite de temporiser apres chaque lancement d'une tache parallele a ete           */ \
                                        /* introduite le 20100122142622 afin de permettre d'eviter de saturer une MACHINE par        */ \
                                        /* le lancement simultane d'activites tres lourdes.                                          */

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        M A C R O S   U T I L E S  :                                                                                               */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   PREMIER_PROCESS                                                                                                               \
                    INDEX0

#define   INITIALISATION_COMMANDE(commande)                                                                                             \
                    Bblock                                                                                                              \
                    INCR(nombre_de_commandes_initialisees,I);                                                                           \
                                                                                                                                        \
                    Test(IFLE(nombre_de_commandes_initialisees,nombre_de_processus_parallelisables))                                    \
                         Bblock                                                                                                         \
                         EGAL(commande,chain_Acopie(commande_unique_a_paralleliser));                                                   \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock                                                                                                              \
                                        /* Introduit le 20090415081717 afin de disposer d'un mode compatible avec la commande        */ \
                                        /* 'v $xcg/parallele.14$K'.                                                                  */

#define   _____UN                                                                                                                       \
                    UN
#define   ___DEUX                                                                                                                       \
                    DEUX
#define   __TROIS                                                                                                                       \
                    TROIS
#define   _QUATRE                                                                                                                       \
                    QUATRE
                                        /* Afin d'ameliorer les tabulations...                                                       */

#define   GENERE_COMMANDE__(commande,numero)                                                                                            \
                    COND(IFNE_chaine(commande,C_VIDE)                                                                                   \
                        ,chain_Aconcaten2(commande                                                                                      \
                                         ,COND(IFNE_chaine(racine_des_fichiers_de_redirection,C_VIDE)                                   \
                                              ,chain_Aconcaten5(C_BLANC                                                                 \
                                                               ,COND(IL_FAUT(executer_les_commandes_sous_CSH)                           \
                                                                    ,C_CSH__REDIRECTION_FICHIER                                         \
                                                                    ,C_SH__REDIRECTION_FICHIER                                          \
                                                                     )                                                                  \
                                                               ,C_BLANC                                                                 \
                                                               ,racine_des_fichiers_de_redirection                                      \
                                                               ,chain_numero(numero,nombre_de_chiffres_a_editer)                        \
                                                                )                                                                       \
                                              ,ccCHAR(C_VIDE)                                                                           \
                                               )                                                                                        \
                                          )                                                                                             \
                        ,ccCHAR(C_VIDE)                                                                                                 \
                         )
#define   GENERE_SEPARATEUR(commande)                                                                                                   \
                    COND(IFNE_chaine(commande,C_VIDE),chaine_separateur,ccCHAR(C_VIDE))
                                        /* Procedures introduites le 20090416094310 afin d'alleger la generation de la liste         */
                                        /* 'liste_des_commandes'...                                                                  */
                                        /*                                                                                           */
                                        /* On notera que 'chaine_separateur' n'est pas insere lorsque la 'commande??' qui precede    */
                                        /* est vide ('v $xcg/parallele.1N$K 20090415114639') afin de maximiser le parallelisme...    */

#define   IL_N_Y_A_AUCUNE_COMMANDE_DE_TYPE_parallele_14                                                                                 \
                    IFET(IFEQ_chaine(commande_unique_a_paralleliser,C_VIDE)                                                             \
                        ,I4ET(IFEQ_chaine(commande11,C_VIDE)                                                                            \
                             ,IFEQ_chaine(commande12,C_VIDE)                                                                            \
                             ,IFEQ_chaine(commande21,C_VIDE)                                                                            \
                             ,IFEQ_chaine(commande22,C_VIDE)                                                                            \
                              )                                                                                                         \
                         )                                                                                                              \
                                        /* Introduit le 20090416135000 afin de simplifier les validations ulterieures, puis          */ \
                                        /* passage d'un 'Logical' a un '#define' le 20090417210844...                                */

#define   COMMANDE_PARALLELE_COURANTE                                                                                                   \
                    COND(IL_FAUT(compatibilite_20120114)                                                                                \
                        ,chain_Aconcaten2(COND(IL_FAUT(executer_les_commandes_sous_CSH)                                                 \
                                              ,ccCHAR(LANCEMENT_D_UNE_COMMANDE_SOUS_CSH)                                                \
                                              ,ccCHAR(LANCEMENT_D_UNE_COMMANDE_SOUS_SH_DE_BASE)                                         \
                                               )                                                                                        \
                                         ,ITb1(commande_courante,INDX(numero_des_process,PREMIER_PROCESS))                              \
                                          )                                                                                             \
                        ,chain_Aconcaten5(COND(IL_FAUT(executer_les_commandes_sous_CSH)                                                 \
                                              ,ccCHAR(LANCEMENT_D_UNE_COMMANDE_SOUS_CSH)                                                \
                                              ,ccCHAR(LANCEMENT_D_UNE_COMMANDE_SOUS_SH)                                                 \
                                               )                                                                                        \
                                         ,quote_des_commandes                                                                           \
                                         ,COND(IZEQ(priorite_des_commandes)                                                             \
                                              ,ccCHAR(C_VIDE)                                                                           \
                                              ,chain_Aconcaten3(COND(IL_FAUT(executer_les_commandes_sous_CSH)                           \
                                                                    ,ccCHAR(CHANGEMENT_DE_PRIORITE_D_UNE_COMMANDE_SOUS_CSH)             \
                                                                    ,ccCHAR(CHANGEMENT_DE_PRIORITE_D_UNE_COMMANDE_SOUS_SH)              \
                                                                     )                                                                  \
                                                               ,chain_Aentier(priorite_des_commandes)                                   \
                                                               ,C_BLANC                                                                 \
                                                                )                                                                       \
                                               )                                                                                        \
                                         ,ITb1(commande_courante,INDX(numero_des_process,PREMIER_PROCESS))                              \
                                         ,quote_des_commandes                                                                           \
                                          )                                                                                             \
                         )                                                                                                              \
                                        /* Commande parallele courante (introduite le 20120114184627...                              */

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        G E S T I O N   " I N T E R N E "   D U   P A R A L L E L I S M E  :                                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
BCommande(nombre_d_arguments,arguments)
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     DEFV(Logical,INIT(compatibilite_20120114,COMPATIBILITE_20120114));
                                        /* Permet de se placer dans l'etat anterieur a l'introduction des 'priorite_des_commandes'.  */
                                        /* On notera que c'est l'etat par defaut et ceci a cause du fait qu'il y a de grosses        */
                                        /* differences entre 'LANCEMENT_D_UNE_COMMANDE_SOUS_SH_DE_BASE' et                           */
                                        /* 'LANCEMENT_D_UNE_COMMANDE_SOUS_SH' en ce qui concerne la disponibilite de 'nice', le      */
                                        /* comportement vis a vis des parentheses ou encore des quotes. Or cette commande est tres   */
                                        /* utilisee par exemple dans 'execRVB' ou encore dans 'v $xcg/FindExec.01$Z PPaRaLlElE'.     */
                                        /* Donc pour ne pas perturber tout cela, retour avant le 20120114181453...                   */

     DEFV(Logical,INIT(bloquer_le_parallelisme,BLOQUER_LE_PARALLELISME));
                                        /* La possibilite d'inhiber le parallelisme directement a ete introduite le 20100630192050   */
                                        /* pour 'v $Falias_execALBUM parallelisme='. Le 20100701095323, la logique de cet indicateur */
                                        /* a ete inversee en passant de 'autoriser_le_parallelisme' a 'bloquer_le_parallelisme'...   */

     DEFV(Logical,INIT(ajuster_automatiquement_PCMemorySizeMB,AJUSTER_AUTOMATIQUEMENT_PCMemorySizeMB));
                                        /* La variable d'environnement '$PCMemorySizeMB' sera par defaut reduite proportionnellement */
                                        /* a 'nombre_de_processus_parallelisables' (introduit le 20120214104603).                    */

     DEFV(Logical,INIT(compatibilite_parallele_14,COMPATIBILITE_PARALLELE_14));
                                        /* La possibilite d'inhiber la compatibilite avec 'v $xcg/parallele.14$K' a ete introduite   */
                                        /* le 20090416105323...                                                                      */
     DEFV(Logical,INIT(en_mode_compatibilite_parallele_14_avertir_s_il_y_a_trop_de_process
                      ,EN_MODE_COMPATIBILITE_PARALLELE_14_AVERTIR_S_IL_Y_A_TROP_DE_PROCESS
                       )
          );
                                        /* La possibilite d'inhiber le message correspondant a ete introduite le 20100412134427...   */
     DEFV(Logical,INIT(dupliquer_N_fois_la_commande,DUPLIQUER_N_FOIS_LA_COMMANDE));
     DEFV(Positive,INIT(nombre_de_duplications_de_la_commande,NOMBRE_DE_PROCESSUS_PARALLELISABLES));
                                        /* Faut-il dupliquer la commande autant de fois qu'il y a de processus paralleles possibles  */
                                        /* ('VRAI') ou pas ('FAUX') ? Cela fut introduit le 20140418122211. On notera qu'avant cette */
                                        /* date, tout se passait comme si cette option (absente alors) etait 'VRAI'. La valeur par   */
                                        /* defaut est devenue 'VRAI' le 20140419102659 afin d'assurer la compatibilite avec les tres */
                                        /* nombreux usages du type 'v $xiac/$Fnota .xcs.Linda.vv.Z''...                              */
                                        /*                                                                                           */
                                        /* Ceci fut complete le 20140419111827 par le nombre de duplications...                      */
     DEFV(CHAR,INIC(POINTERc(commande_unique_a_paralleliser),C_VIDE));
     DEFV(CHAR,INIC(POINTERc(commande11),C_VIDE));
     DEFV(CHAR,INIC(POINTERc(commande12),C_VIDE));
     DEFV(CHAR,INIC(POINTERc(commande21),C_VIDE));
     DEFV(CHAR,INIC(POINTERc(commande22),C_VIDE));
                                        /* Introduit le 20090415081717 afin de disposer d'un mode compatible avec la commande        */
                                        /* 'v $xcg/parallele.14$K'.                                                                  */

     DEFV(CHAR,INIC(POINTERc(liste_des_commandes),C_VIDE));
                                        /* Liste des commandes a paralleliser, sous la forme :                                       */
                                        /*                                                                                           */
                                        /*                  COMMANDE1 # COMMANDE2 # (...) # COMMANDEi # (...) # COMMANDEn            */
                                        /*                                                                                           */
                                        /* en supposant que 'caractere_de_separation_des_commandes' soit '#'. D'autre part, chaque   */
                                        /* 'COMMANDEi' peut etre de la forme :                                                       */
                                        /*                                                                                           */
                                        /*                  COMMANDEi1 ; COMMANDEi2 ; (...) ; COMMANDEij ; (...) ; COMMANDEim        */
                                        /*                                                                                           */
                                        /* ou 'COMMANDEij' est une commande "simple" et les espaces ci-dessus etant purement         */
                                        /* "cosmetiques"...                                                                          */

     DEFV(CHAR,INIC(POINTERc(racine_des_fichiers_de_redirection),C_VIDE));
     DEFV(Positive,INIT(premier_numero,PREMIER_NUMERO));
     DEFV(Positive,INIT(nombre_de_chiffres_a_editer,NOMBRE_DE_CHIFFRES_A_EDITER));
                                        /* Introduit le 20111116210724 afin de pouvoir eventuellement rediriger les sorties...       */

     DEFV(Logical,INIT(executer_les_commandes_sous_CSH,EXECUTER_LES_COMMANDES_SOUS_CSH));
                                        /* La possibilite d'executer les commandes sous '$CSH' a ete introduite le 20091021093824,   */
                                        /* la valeur par defaut assurant la compatibilite anterieure...                              */

     DEFV(CHAR,INIT(caractere_de_separation_des_commandes,CARACTERE_DE_SEPARATION_DES_COMMANDES));
                                        /* Caractere de separation des commandes a paralleliser (voir le commentaire precedent...).  */

     DEFV(Positive,INIT(nombre_de_processus_parallelisables,NOMBRE_DE_PROCESSUS_PARALLELISABLES));
                                        /* Nombre de processus parallelisables.                                                      */
                                        /*                                                                                           */
                                        /* On notera le 20090415132416 qu'en faisant :                                               */
                                        /*                                                                                           */
                                        /*                  NombreProcessParalleles=1                                                */
                                        /*                                                                                           */
                                        /* on se place dans une situation equivalente au :                                           */
                                        /*                                                                                           */
                                        /*                  parallelisme=FAUX                                                        */
                                        /*                                                                                           */
                                        /* de 'v $xcg/parallele.14$K, c'est-a-dire que l'on se met en mode "sequentiel"...           */

     DEFV(Logical,INIT(editer_les_commandes_avant_leur_lancement,EDITER_LES_COMMANDES_AVANT_LEUR_LANCEMENT));
                                        /* Afin de permettre d'editer les commandes avant le lancement et dans un ordre qui n'est    */
                                        /* pas a priori l'ordre numerique 'numero_des_process' (introduit le 20120114184627)...      */

     DEFV(CHAR,INIC(POINTERc(quote_des_commandes),QUOTE_DES_COMMANDES));
                                        /* Afin de pouvoir encadrer les commandes (introduit le 20120114190709)...                   */

     DEFV(Positive,INIT(priorite_des_commandes,PRIORITE_DES_COMMANDES));
                                        /* Priorite d'ordonnancement ("scheduling") des commandes (introduite le 20120114181453)...  */
     DEFV(Int,INIT(temporisation_apres_chaque_lancement,TEMPORISATION_APRES_CHAQUE_LANCEMENT));
                                        /* La possibilite de temporiser apres chaque lancement d'une tache parallele a ete           */
                                        /* introduite le 20100122142622 afin de permettre d'eviter de saturer une MACHINE par        */
                                        /* le lancement simultane d'activites tres lourdes.                                          */

     DEFV(Int,INIT(index_du_premier_caractere_de_la_commande_courante,PREMIER_CARACTERE));
     DEFV(Logical,INIT(toutes_les_commandes_ont_ete_recuperees,FAUX));
                                        /* Afin de recuperer toutes les commandes a paralleliser...                                  */
     /*..............................................................................................................................*/
     GET_ARGUMENTS_(nombre_d_arguments
                   ,BLOC(GET_ARGUMENT_L("compatibilite_20120114=",compatibilite_20120114);

                         GET_ARGUMENT_L("sequentiel=""seq=",bloquer_le_parallelisme);
                         GET_ARGUMENT_N("parallelisme=""parallele=""para=",bloquer_le_parallelisme);
                                        /* Argument introduit le 20100630192050. Le 20100701095323, la logique de cet indicateur     */
                                        /* a ete inversee en passant de 'autoriser_le_parallelisme' a 'bloquer_le_parallelisme'...   */

                         GET_ARGUMENT_L("PCMemorySizeMB=""PCM=",ajuster_automatiquement_PCMemorySizeMB);
                                        /* Arguments introduits le 20120214104603...                                                 */

                         GET_ARGUMENT_L("compatibilite_parallele_14=""parallele_14=""p14=",compatibilite_parallele_14);
                         GET_ARGUMENT_L("avertir_trop_de_process_compatibilite_parallele_14=""atp="
                                       ,en_mode_compatibilite_parallele_14_avertir_s_il_y_a_trop_de_process
                                        );
                                        /* Arguments introduits le 20100412134427...                                                 */

                         GET_ARGUMENT_L("dupliquer_N_fois=""dupliquer=""dup=",dupliquer_N_fois_la_commande);
                         GET_ARGUMENT_I("nombre_duplications=""duplications=""ndup=",nombre_de_duplications_de_la_commande);
                                        /* Arguments introduits le 20140418122211 et completes le 20140419111827...                  */

                         GET_ARGUMENT_C("commande=""cm=""c=""C=",commande_unique_a_paralleliser);

                         GET_ARGUMENT_C("commande1=""commande11=""cm1=""c1=""c11=""C1=""C11=",commande11);
                         GET_ARGUMENT_C("commande2=""commande12=""cm2=""c2=""c12=""C2=""C12=",commande12);
                         GET_ARGUMENT_C("commande3=""commande21=""cm3=""c3=""c21=""C3=""C21=",commande21);
                         GET_ARGUMENT_C("commande4=""commande22=""cm4=""c4=""c22=""C4=""C22=",commande22);
                                        /* Le 20090415111836, je note que les cinq 'GET_ARGUMENT_C(...)'s qui precedent doivent etre */
                                        /* identiques a ceux de 'v $xcg/parallele.14$K GET_ARGUMENT_C' pour assurer la compatibilite */
                                        /* de 'v $xcg/parallele.1N$K' et de 'v $xcg/parallele.14$K'.                                 */

                         GET_ARGUMENT_C("liste_commandes=""lc=""liste=""commandes=""cms=""cs=""Cs=",liste_des_commandes);

                         GET_ARGUMENT_C("fichiers_redirection=""redirection=""fr=",racine_des_fichiers_de_redirection);
                         GET_ARGUMENT_I("chiffres=",nombre_de_chiffres_a_editer);
                         GET_ARGUMENT_I("premier_numero=""premier=""p=",premier_numero);
                                        /* Arguments introduits le 20111116210724...                                                 */

                         GET_ARGUMENT_L("CSH=""csh=",executer_les_commandes_sous_CSH);
                         GET_ARGUMENT_N("SH=""sh=",executer_les_commandes_sous_CSH);

                         GET_ARGUMENT_K("separateur=""sep=",caractere_de_separation_des_commandes);

                         GET_ARGUMENT_I("NombreProcessParalleles=""process=""processus=""np=""nombre=""NP="
                                       ,nombre_de_processus_parallelisables
                                        );

                         GET_ARGUMENT_L("editer_commandes=""ec=",editer_les_commandes_avant_leur_lancement);
                                        /* Arguments introduits le 20120114184627...                                                 */

                         PROCESS_ARGUMENT_C("quotes=""q=",quote_des_commandes
                                           ,BLOC(VIDE;)
                                           ,BLOC(Test(IFGT(chain_Xtaille(quote_des_commandes),size_CHAR))
                                                      Bblock
                                                      PRINT_ATTENTION("la 'quote' des commandes est a priori un caractere unique");
                                                      Eblock
                                                 ATes
                                                      Bblock
                                                      Eblock
                                                 ETes
                                                 )
                                            );
                                        /* Arguments introduits le 20120114190709...                                                 */

                         GET_ARGUMENT_I("temporisation=""tempo=",temporisation_apres_chaque_lancement);
                                        /* Arguments introduits le 20100122142622...                                                 */
                         GET_ARGUMENT_I("priorite_commandes=""priorite=""nice=",priorite_des_commandes);
                                        /* Arguments introduits le 20100122142622...                                                 */
                         )
                    );

     Test(IL_FAUT(compatibilite_20120114))
                                        /* Test introduit le 20120115120709...                                                       */
          Bblock
          Eblock
     ATes
          Bblock
          Test(IFET(IZGT(priorite_des_commandes)
                   ,IFET(IFNE_chaine(quote_des_commandes,C_APOSTROPHE)
                        ,IFNE_chaine(quote_des_commandes,C_QUOTE)
                         )
                    )
               )
                                        /* Test introduit le 20120114192311...                                                       */
               Bblock
               PRINT_ATTENTION("il est preferable de 'quoter' les commandes non prioritaires");
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     ETes

     begin_nouveau_block
          Bblock
          DEFV(CHAR,INIS(DTb0(chaine_separateur),Ichaine01(caractere_de_separation_des_commandes)));
                                        /* ATTENTION : c'est 'INIS(...)' qui est utilise (et non pas 'INIT(...)') afin de ne pas     */
                                        /* parentheser la liste 'Ichaine01(...)'.                                                    */

          Test(IL_FAUT(bloquer_le_parallelisme))
                                        /* Test introduit le 20100630192050. Le 20100701095323, la logique de cet indicateur         */
                                        /* a ete inversee en passant de 'autoriser_le_parallelisme' a 'bloquer_le_parallelisme'...   */
               Bblock
               EGAL(nombre_de_processus_parallelisables,UN);
                                        /* Et voila comment bloquer le parallelisme...                                               */
               Eblock
          ATes
               Bblock
               Eblock
          ETes

          Test(IL_FAUT(compatibilite_parallele_14))
                                        /* Test introduit le 20090416105323...                                                       */
               Bblock
               Test(IFEQ_chaine(liste_des_commandes,C_VIDE))
                                        /* Lorsque la liste des commandes est vide, cela declenche le mode de compatibilite avec     */
                                        /* '$xcg/parallele.14$K'. Les commandes individuelles vont etre concatenees (si elles        */
                                        /* existent afin de donner naissance a la liste...).                                         */
                    Bblock
                    Test(IFGT(nombre_de_processus_parallelisables,NOMBRE_DE_PROCESSUS_PARALLELISABLES_4))
                         Bblock
                         Test(EST_VRAI(en_mode_compatibilite_parallele_14_avertir_s_il_y_a_trop_de_process))
                                        /* Test introduit le 20100412134427...                                                       */
                              Bblock
                              PRINT_ATTENTION("en mode compatible '$xcg/parallele.14$K' le nombre de process paralleles est limite");
                              CAL1(Prer2("(%d process etaient demandes alors que %d seront utilises au maximum)\n"
                                        ,nombre_de_processus_parallelisables
                                        ,NOMBRE_DE_PROCESSUS_PARALLELISABLES_4
                                         )
                                   );
                              Eblock
                         ATes
                              Bblock
                              Eblock
                         ETes

                         EGAL(nombre_de_processus_parallelisables,NOMBRE_DE_PROCESSUS_PARALLELISABLES_4);
                                        /* Limitation introduite le 20090415123925...                                                */
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes

                    Test(IFNE_chaine(commande_unique_a_paralleliser,C_VIDE))
                         Bblock
                         Test(I4ET(IFEQ_chaine(commande11,C_VIDE)
                                  ,IFEQ_chaine(commande12,C_VIDE)
                                  ,IFEQ_chaine(commande21,C_VIDE)
                                  ,IFEQ_chaine(commande22,C_VIDE)
                                   )
                              )
                              Bblock
                              DEFV(Int,INIT(nombre_de_commandes_initialisees,ZERO));

                              INITIALISATION_COMMANDE(commande11);
                              INITIALISATION_COMMANDE(commande12);
                              INITIALISATION_COMMANDE(commande21);
                              INITIALISATION_COMMANDE(commande22);
                              Eblock
                         ATes
                              Bblock
                              PRINT_ATTENTION("la 'commande unique' est ignoree, l'une au moins des quatre commandes etant definie");
                              CAL1(Prer1("(elle etait '%s')\n",commande_unique_a_paralleliser));
                              Eblock
                         ETes
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes

                    EGAL(liste_des_commandes
                        ,chain_Aconcaten7(GENERE_COMMANDE__(commande11,_____UN),GENERE_SEPARATEUR(commande11)
                                         ,GENERE_COMMANDE__(commande12,___DEUX),GENERE_SEPARATEUR(commande12)
                                         ,GENERE_COMMANDE__(commande21,__TROIS),GENERE_SEPARATEUR(commande21)
                                         ,GENERE_COMMANDE__(commande22,_QUATRE)
                                          )
                         );
                    Eblock
               ATes
                    Bblock
                    Test(EST_FAUX(IL_N_Y_A_AUCUNE_COMMANDE_DE_TYPE_parallele_14))
                         Bblock
                         PRINT_ATTENTION("le mode compatible '$xcg/parallele.14$K' est bloque, une liste de commandes etant presente");
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes
                    Eblock
               ETes
               Eblock
          ATes
               Bblock
               Test(EST_FAUX(IL_N_Y_A_AUCUNE_COMMANDE_DE_TYPE_parallele_14))
                    Bblock
                    Test(IL_FAUT(dupliquer_N_fois_la_commande))
                                        /* Test introduit le 20140418122211...                                                       */
                         Bblock
                         DEFV(Int,INIT(numero_courant,premier_numero));
                                        /* Numero courant eventuel du fichier de redirection...                                      */

                         Repe(nombre_de_duplications_de_la_commande)
                              Bblock
                              EGAL(liste_des_commandes
                                  ,chain_Aconcaten2(liste_des_commandes,GENERE_COMMANDE__(commande_unique_a_paralleliser,numero_courant))
                                   );
                                        /* Cette possibilite a ete introduite le 20100329085302 afin de favoriser l'execution de     */
                                        /* 'v $xcs/Linda$vv$Z' (par exemple dans 'v $xiac/$Fnota .xcs.Linda.vv.Z').                  */

                              Test(IFLT(compteur_des_repetitions_du_Repe,nombre_de_duplications_de_la_commande))
                                        /* ATTENTION, jusqu'au 20200114143902, il y avait ici (par erreur ?) :                       */
                                        /*                                                                                           */
                                        /*        Test(IFLT(compteur_des_repetitions_du_Repe,nombre_de_processus_parallelisables))   */
                                        /*                                                                                           */
                                        /* Cela s'est vu en introduisant l'alias 'v $xE/.alias.2$vv$y execPar_F'...                  */
                                   Bblock
                                   EGAL(liste_des_commandes
                                       ,chain_Aconcaten2(liste_des_commandes,GENERE_SEPARATEUR(commande_unique_a_paralleliser))
                                        );
                                   Eblock
                              ATes
                                   Bblock
                                   Eblock
                              ETes

                              INCR(numero_courant,I);
                                        /* Numero courant eventuel du fichier de redirection...                                      */
                              Eblock
                         ERep
                         Eblock
                    ATes
                         Bblock
                         EGAL(liste_des_commandes
                             ,chain_Aconcaten2(liste_des_commandes,GENERE_COMMANDE__(commande_unique_a_paralleliser,premier_numero))
                              );
                                        /* Introduit le 20140418122211 a cause de 'v $xcg/FindExec.01$Z LiMiTeUr' qui met toutes les */
                                        /* commandes "bout a bout" seperees par le "#"...                                            */
                         Eblock
                    ETes
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes
               Eblock
          ETes
          Eblock
     end_nouveau_block

     Test(IL_FAUT(ajuster_automatiquement_PCMemorySizeMB))
                                        /* Test introduit le 20120214104603.                                                         */
          Bblock
          Pval("PCMemorySizeMB"
              ,DIVI(sHOTE_____TAILLE_DE_LA_MEMOIRE_DE_REFERENCE_EN_MEGA_OCTETS,nombre_de_processus_parallelisables)
               );
                                        /* Ainsi le pourcentage de la memoire physique a priori utilisable est partage equitablement */
                                        /* entre tous les processus qui vont etre lances (introduit le 20120214104603).              */
          Eblock
     ATes
          Bblock
          Eblock
     ETes

     Tant(EST_FAUX(toutes_les_commandes_ont_ete_recuperees))
          Bblock
                                        /* Bouclage sur l'integralite des commandes arguments :                                      */
          DEFV(CHAR,POINTERc(DTb1(commande_courante,nombre_de_processus_parallelisables)));
                                        /* Liste des commandes courantes parallelisees.                                              */
          DEFV(processus,DTb1(process_parallelises,nombre_de_processus_parallelisables));
                                        /* Identificateur des process correspondant aux commandes courantes parallelisees.           */
          DEFV(Int,INIT(numero_des_process,PREMIER_PROCESS));
                                        /* Index des differents process...                                                           */

          Tant(IFET(IFLE(numero_des_process,LSTX(PREMIER_PROCESS,nombre_de_processus_parallelisables))
                   ,EST_FAUX(toutes_les_commandes_ont_ete_recuperees)
                    )
               )
                                        /* Bouclage sur un "paquet" de 'nombre_de_processus_parallelisables' commandes arguments :   */
               Bblock
               BSaveModifyVariable(Int
                                  ,chain_copie_____index_du_premier_caractere_d_une_chaineA
                                  ,index_du_premier_caractere_de_la_commande_courante
                                   );
               BSaveModifyVariable(CHAR
                                  ,chain_copie_____caractere_d_arret_secondaire
                                  ,caractere_de_separation_des_commandes
                                   );
               BSaveModifyVariable(Logical
                                  ,chain_copie_____copier_le_caractere_d_arret_secondaire
                                  ,FAUX
                                   );
               BSaveModifyVariable(Int
                                  ,chain_copie_____premier_index_de_test_du_caractere_d_arret_secondaire
                                  ,PREMIER_CARACTERE
                                   );
                                        /* Afin de recuperer la commande courante dans la liste des commandes.                       */

               EGAL(ITb1(commande_courante,INDX(numero_des_process,PREMIER_PROCESS)),chain_Acopie(liste_des_commandes));
                                        /* Recuperation de la commande courante.                                                     */
                                        /*                                                                                           */
                                        /* On notera qu'il n'est en fait pas utile que 'commande_courante' soit un vecteur de        */
                                        /* chaines de caracteres. Il suffirait en fait de le definir par:                            */
                                        /*                                                                                           */
                                        /*                  DEFV(CHAR,POINTERc(commande_courante));                                  */
                                        /*                                                                                           */
                                        /* mais on ne sait jamais, peut-etre que plus tard...                                        */

               ESaveModifyVariable(Int,chain_copie_____premier_index_de_test_du_caractere_d_arret_secondaire);
               ESaveModifyVariable(Logical,chain_copie_____copier_le_caractere_d_arret_secondaire);
               ESaveModifyVariable(CHAR,chain_copie_____caractere_d_arret_secondaire);
               ESaveModifyVariable(Int,chain_copie_____index_du_premier_caractere_d_une_chaineA);
                                        /* Restaurations...                                                                          */

               iPARALLELE(BLOC(
                               Bblock
                               Test(IL_FAUT(editer_les_commandes_avant_leur_lancement))
                                    Bblock
                                    CAL3(Prme3("Commande parallele %0*d='%s'\n"
                                              ,NOMBRE_DE_CHIFFRES_DECIMAUX(nombre_de_processus_parallelisables)
                                              ,numero_des_process
                                              ,COMMANDE_PARALLELE_COURANTE
                                               )
                                         );
                                        /* Possibilite introduite le 20120114184627...                                               */
                                        /*                                                                                           */
                                        /* Le 20120115172535 fut introduit l'edition de 'numero_des_process'...                      */
                                        /*                                                                                           */
                                        /* On notera evidemment que les differentes commandes ne sortent pas necessairement dans     */
                                        /* l'ordre numerique de 'numero_des_process' a cause de 'iPARALLELE(...)' qui possede un     */
                                        /* fonctionnement asynchrone...                                                              */
                                    Eblock
                               ATes
                                    Bblock
                                    Eblock
                               ETes

                               CALS(SYSTEM(COMMANDE_PARALLELE_COURANTE));
                               Eblock
                               )
                         ,ITb1(process_parallelises,INDX(numero_des_process,PREMIER_PROCESS))
                          );
                                        /* Lancement en parallele de la commande courante.                                           */
                                        /*                                                                                           */
                                        /* On notera le 20090415114639 le fonctionnement suivant :                                   */
                                        /*                                                                                           */
                                        /* soit (par exemple...) :                                                                   */
                                        /*                                                                                           */
                                        /*                  NombreProcessParalleles=2                                                */
                                        /*                                                                                           */
                                        /* Ensuite :                                                                                 */
                                        /*                                                                                           */
                                        /*                  liste_commandes="COMMANDE1#COMMANDE2"                                    */
                                        /*                                                                                           */
                                        /* provoquera l'execution simultanee et parallele de 'COMMANDE1' et 'COMMANDE2', alors       */
                                        /* que :                                                                                     */
                                        /*                                                                                           */
                                        /*                  liste_commandes="COMMANDE1##COMMANDE2"                                   */
                                        /*                                             _                                             */
                                        /* provoquera l'execution simultanee et parallele de 'COMMANDE1' et d'une commande vide      */
                                        /* a cause du deuxieme '#'), puis ENSUITE de 'COMMANDE2'. C'est pour eviter cela que le      */
                                        /* separateur (via 'chaine_separateur') n'est pas insere si une commande vide le precede     */
                                        /* lors du mode compatible '$xcg/parallele.14$K'...                                          */
                                        /*                                                                                           */
                                        /* Le 20091021093824 fut introduite la possibilite d'executer les commandes sous '$CSH',     */
                                        /* autorisant ainsi l'utilisation d'alias...                                                 */

               DODO(temporisation_apres_chaque_lancement);
                                        /* Temporisation eventuelle introduite le 20100122142622...                                  */
                                        /*                                                                                           */
                                        /* Celle-ci est destinee a permettre (si besoin est) d'eviter de saturer une MACHINE par     */
                                        /* le lancement simultane d'activites tres lourdes. C'est par exemple le cas avec :          */
                                        /*                                                                                           */
                                        /*                  execRVB   $xci/accumule.41$X ...                                         */
                                        /*                                                                                           */
                                        /* dans 'v $xiirc/$Fnota execRVB....xci.accumule.41.X' qui provoquent la lecture simultanee  */
                                        /* de tres gros fichiers au demarrage...                                                     */

               EGAL(index_du_premier_caractere_de_la_commande_courante
                   ,chain_copie_____successeur_de_l_index_du_dernier_caractere_d_une_chaineA
                    );
                                        /* Pour preparer le 'chain_Acopie(...)' eventuel suivant...                                  */

               Test(EST_VRAI(chain_copie_____la_chaineA_a_ete_copiee_jusqu_au_END_OF_CHAIN))
                    Bblock
                    EGAL(toutes_les_commandes_ont_ete_recuperees,VRAI);
                                        /* Toutes les commandes ont apparemment ete recuperees...                                    */
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes

               INCR(numero_des_process,I);
               Eblock
          ETan

          Tant(IFGT(numero_des_process,PREMIER_PROCESS))
               Bblock
               DECR(numero_des_process,I);

               WAIT(ITb1(process_parallelises,INDX(numero_des_process,PREMIER_PROCESS)));
                                        /* Attente de fin de toutes les commandes lancees en parallele. En fait, ainsi on            */
                                        /* attend celle dont l'execution est la plus longue...                                       */
               Eblock
          ETan
          Eblock
     ETan

     RETU_Commande;
     Eblock
ECommande



Copyright © Jean-François COLONNA, 2019-2024.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / École polytechnique, Institut Polytechnique de Paris, 2019-2024.