!JustAHack

(jouer avec le module taskwindow sous WIMP)
La version actuelle est v0.2
Auteur: Benoît GILON
Logo de HTMLEdit v3

Présentation

!JustAHack est une application simple qui illustre l'utilisation du module Taskwindow d'Acorn par des applications sous le WIMP de RO3 ou plus récent.
Bien que cela ne soit pas l'article prévu pour la prochaine parution de CAUGers, article sur le Multi-threading préemptif (d'où le nom !JustAHack). Le sujet traité n'est toutefois pas éloigné des points traités dans ce dernier.
!JustAHack est une application WIMP basée sur la Toolbox Acorn et qui: !JustAHack est juste une application exemple, mon objectif ici n'est pas de fournir au lecteur une librarie prête à être utilisée au sein de leurs propres applications. Un peu plus de travail est requis pour monter ce projet.
Si un lecteur est intéressé par un tel sujet, et peut investir un peu de temps, alors, une direction à emprunter est la faisabilité de créer une Application Wimp générique capable de mettre à jour des gadgets Wimp au nom d'autres tâches tournant, elles, sous TaskWindow.

Guide d'utilisation de !JustAHack

!JustAHack est une application pour mesurer les performances relatives de différents algorithmes de tri sur des fichiers texte. Lorsque vous lancez !JustAHack, il installe une icône sur la barre d'icônes. À partir de ce moment, vous pouvez déposer des icônes de fichiers texte sur cette dernière: Pour chaque fichier déposé, !JustHack ouvrira une fenêtre similaire à la suivante:
Fenêtre principale de !JustAHack
Une manipulation amusante à essayer est de déposer un groupe de fichiers texte (pas plus de 4 ;-) sinon votre bureau risque de devenir méconnaissable tout au moins sur un écran VGA) sur l'icône de !JustAHack sur la barre d'icônes; puis de sélectionner l'entrée "Exécution paralèlle" dans le menu rattaché à l'icône, simulant ainsi des clicks sur le bouton action "Lancer" de chaque fenêtre ouverte de l'application; Voici quelques applications soeur à lancer à côté de !JustAHack:

Comment ça marche

ModuleJAHSupport

Afin de gérer un nombre variables de tâches TaskWindow sans trop saturer le disque par des I/O de chargement de fichiers, J'ai mis au point un module nommé JAHSupport qui offre cinq commandes:
JAHLoadFile <clé> <chemindufichier>
Charge un fichier dans la RMA et assigne une valeur clé au contenu pour future reference; la version actuelle ne lira pas au delà de la 1024ème ligne physique du fichier. La sortie (flux de sortie standard) de cette commande consiste simplement en le nombre de lignes en mémoire suite au chargement du fichier (ce nombre est alors routé vers l'application parente via le mécanisme de transfert de messages lié à TaskWindow).
JAHQSort <clé> [limite], JAHBSort <clé> [limite], JAHSSort <clé> [limite]
Trie un fichier en memoire (le résultat de ce tri étant mis au rebut): trois algorithmes sont traités d'où trois commandes; La sortie de chacune de ces commandes est une liste de nombres donnat l'indice de la ligne en cours de traitements de 0 à l'indice de la dernière ligne lue précédemment en mé le paramètre optionnel "limite" permet de filtrer la sortie en ne déclenchant la production d'une ligne physique, réduisant ainsi le temps mis par le processus à s'exécuter.
JAHUnLoadFile <clé>
Indique au module de libérer les ressources (mémoire RMA) allouées pour le chargement d'un fichier;
Il n'y a ni SWI, ni getionnaire d'interruptions.
Rendre le chargement du fichier séparé des phase de tri permet d'appliquer de façon concurrente plusieurs processus de tri et rend la démarche globale plus efficiente (moins d'I/O disque).

Application WIMP JAH

!JustAHack inclue des fonctionalités qui apparurent pour la première fois dans mon application !TopTen (v0.6.5); Pour chaque fichier déposé au dessus de l'icône !JustAHack, l'application crée la structure suivante en mémoire:
#define NUMBER_SORT_ALGO 3
enum    {
        KBUBLE = 0, KQUICK, KSELECT, KLOAD
        };
/* The "tclient" structure serves for managing the communication with a
   taskwindow child task */
typedef struct
        {
        int twcid; /* wimp task handle of the taskwindow task */
        int issuspended; /* is it currently suspended? */
        /* Toolbox components upgradable according to the output
           of such taskwindow task*/
        ComponentId pgbcid, dispcid, srcid, killtcid;
        /* "Status" of the taskwindow child task */
        enum    {
                INITIAL= 0 /* WAITING FOR CIDLOAD */,
                WAITFORCR /* WAITING FOR NR */,
                LOADED
                } status;
        } tclient;
typedef struct
        {
        struct MinNode mnode; /* used for chaining the structure as a node */
        int key; /* external ID used for submitting requests to the module */
        size_t nbusy; /* # of child tasks active */
        tclient client[NUMBER_SORT_ALGO+1];
        /* Acorn Toolbox objectid for this window */
        ObjectId woid;
        /* Complete pathname for the file being "processed" */
        char fname[FILENAME_MAX+1];
        } filestruct;
Le comportement dynamique de l'application peut être décrit par les diagrammes ci-dessous qui montrent les étapes nombreuses traversées lors d'une action utilisateur ou lors de l'occurence d'un évènement externe (en dehors de l'application WIMP): Comportement dynamique pour !JustAHack
Note: si vous avez de la peine è lire le diagramme ci-dessus, sachez que le fichier Draw original est inclus dans l'archive complète de !JustAHack chargeable à partir de la Page principale de !JustAHack.
Un point d'intérêt est de savoir comment !JustAHack implémente l'"Exécution concurrente": ceci est une fonction callback enregistrée pour être appelée lorsque l'utilisateur clique sur l'entrée "Exécution concurrente" dans le menu de l'icône.
static int parallelrun_event(int event_code,
        ToolboxEvent *event, IdBlock *id_block, void *handle)
{
const ActionButtonSelectedEvent monevent = {
        { 16, 0, ActionButton_Selected, ActionButton_Selected_Default }
        };
struct MinNode *pw;
filestruct *pf;
/* Examine every file structure in the chain */
for(pw= mafilelist.mlh_Head; pw->mln_Succ; pw= pw->mln_Succ)
        {
        /* Compute structure base address from one of its fields' address */
        pf= (filestruct *) ((char *) pw - offsetof(filestruct, mnode));
        /* Only if Sort button is unfaded */
        if(pf->nbusy == 0 && pf->client[KLOAD].status== LOADED)
                /* Raise a toolbox event */
                (void) toolbox_raise_toolbox_event(0,
                        pf->woid, KACTBUTSRT, (ToolboxEvent *) &monevent);
        }
return 1;
}

Notes finales

Comportement du module Taskwindow d'Acorn

Une recherche que j'ai mené durant la phase de conception fut de déterminer à quel instant exact le module Taskwindow Acorn envoie un message TaskWindow_Output à la tâche parente, selon le volume de données en attente d'être délivré (sortie du flux standard de la tâche fille Taskwindow). J'ai découvert que le type de bufferisation effectué est le type "full" avec une taille de buffer aux alentours de 126 ce qui est approximativement la moitié de la taille disponible dans un message WIMP TaskWindowOutput. Comme il est nécessaire que la tâche parente soit avertie ASAP du progrès atteint par la tâche fille Taskwindow, toutes les sorties de ces dernières adoptent le format suivant:
  1. 0 '*'
  2. 1:10 indicateur de progrès (justifié à droite)
  3. 11:124 ' ' (caractère espace)
  4. 125 '\n'
Ainsi je suis sûr que la sortie d'une valeur de progression soit convertie directement en un message WIMP.

Outil d'équilibrage de charge

Depuis la version v0.2 de !JustAHack, le fichier Messages contient trois nouvelles entrées:
  1. LIMITQ (Quick)
  2. LIMITB (Bubble)
  3. LIMITS (Select)
qui contiennent le paramètre "limite" fourni à la commande tri du module JAHSupportpour chaque algorithme. Pour un algorithme donné, plus grande est cette valeur, moins de sortie est générée par la tâche fille associée et moins de temps cela prend pour sa completion.