Bops permet l'accès a des piles. Les piles sont des types simples de données, elles sont communément appelées LIFO (Last In First Out) stacks.
Leur gestion a le même niveau de difficulté que la gestion d'une pile d'assiettes dans un placard, cependant Bops a la particularité de rendre cette pile extensible, il agrandit votre placard lorsque vous voulez ajouter une assiette alors que celle du dessus de la pile touche déjà le haut du placard. il n'a de limites que celles imposées par le plafond de la cuisine (i.e. par la mémoire allouable disponible).
Assez généralement dans leurs utilisations courantes, les piles n'ont pas une très grande taille et l'extensibilité n'est pas une fonctionnalité très importante, elle décharge cependant le programmeur du choix d'une taille à allouer ou de la gestion du parametrage de cette taille par un utilisateur.
Il est donc interessant de proposer cette fonctionnalité d'autant que son coût en ressources est faible.
Cette gestion de l'extensibilité de la pile demande a bops peu d'utilisation supplementaire de ressources, il n'execute de code supplémentaire qu'en cas de dépassement de capacité actuelle de la pile et aussi un peu lorsqu'une allocation ajoutée à la pile n'est plus utilisée.
La stratégie d'extension de la pile est paramétrable mais Bops propose un paramètrage par defaut qui convient pour beaucoup de cas d'utilisation des piles.
Pour paramétrer l'extension de la pile, l'utilisateur indique une allocation primaire, le nombre d'éléments disponibles dans la pile à sa création, et une allocation secondaire, le nombre d'éléments alloués lorsque l'allocation primaire (ou une allocation secondaire précédente) ne suffit plus. Bops propose des valeurs par défaut : il calcule le nombre d'éléments qui occupent une page de votre machine.
Afin de limiter les onereuses allocations et libérations de mémoire, Bops a une gestion un peu paresseuse de l'espace, lorsqu'une allocation secondaire n'est plus utilisée, il ne la libère pas d'emblée mais regarde s'il n'y a pas une seconde allocation non utilisée et la libère si c'est le cas. En quelque sorte, il garde toujours une allocation d'avance lorsqu'il en a de disponible, cela peut se réveler une gestion particulièrement économe lorsque le haut de la pile fluctue entre la fin d'une allocation et le début d'une autre.
Cette stratégie simple (mais efficace) n'est pas paramètrable (on ne peut fixer le nombre d'allocations que Bops doit garder d'avance), ce serait une complication que je juge inutile, le choix des allocations primaires et secondaires est sans doute très largement suffisant pour l'immense majorité des utilisations des piles. Laisser Bops choisir ces allocations est aussi un bon choix dans la plupart des cas. A moins que votre pile n'ait qu'une hauteur assez petite pour ne jamais dépasser l'allocation primaire, prenez les valeurs par défaut ou un de leur multiple, le programme bopinfo de Bop-utils vous indiquera les valeurs par défaut calculées pour votre plateforme.
Pour une bonne introduction aux piles, voir ce cours en français.
Les fonctionnalités étendues permettant de n'empiler que sous condition sont détaillées dans le chapitre consacré à l'API détaillée.
Bops utilise principalement 2 types (typedef de structures) de données :
Ces structures de données ne devraient être utilisée que par l'intermédiaire de l'API, celle-ci étant supposée assurer la compatibilité, les structures étant par elle-même sujettes au changement.
Elles permettent de créer/supprimer des piles, d'empiler et de dépiler (terme employé de manière peu conforme au dictionnaire, il s'agit ici de l'inverse d'empiler), d'associer des données à ces éléments etc.
Allocation/suppression d'une pile.
Création/suppression, accès aux éléments.
Accès aux données à partir d'un élément.
Allocation/suppression d'une pile.
Création/suppression, accès aux éléments.
Accès aux données à partir d'un élément.
Précision terminologique : Lorsqu'il est parlé plus bas de pile étendue, cela n'a aucun rapport avec l'extensibilité de la taille de la pile, il s'agit d'un raccourci pour parler d'une pile pour laquelle les fonctionnalités étendues sont permises.
Un des interêts des fonctions étendues est de permettre d'éviter une récursion infinie dans une exploration de graphes cycliques par une technique de pile.
La fonction bopsXSet permet à la pile de se "remémorer" les données qu'elle empile par bopsXPush.
Typiquement, bopXSet est appelée après la création de la pile et bopsXUnset n'est jamais appelé,
mais elle peut, comme bopsXUnset, être appelée à n'importe quel moment de la vie de la pile.
Nota bene : Ce sont les données et leur longueur qui sont remémorées, non leur adresse et leur longueur.
Il est possible d'appeler les fonctions étendues sur une pile non-étendue et, inversement, les fonctions non-étendues sur une pile étendue. Il est dans ce cas necessaire de bien connaitre leur comportement.
Les fonctions non-étendues se comporte de la même manière que la pile soit ou non étendue.
Les fonctions étendues se comportent comme des fonctions non-étendues lorsqu'elles sont appliquées à une pile non-étendue.
Pour qu'une donnée soit remémorée, il faut que la pile soit une pile étendue (par bopsXSet)
et qu'elle ait été empilée par bopsXPush.
Pour qu'une donnée soit oubliée, il faut que la pile soit étendue
et qu'elle ait été dépilée par bopsXPop
(ceci qu'elle ait ou non été remémorée lors de l'empilement de l'élément qui vient d'être dépilée).
Très généralement, à moins d'avoir de bonnes raisons d'avoir concu differement un logiciel utilisant Bops,
il est préférable d'utiliser soit des fonctions non-étendues sur une pile non-étendue
soit des fonctions étendues sur une pile étendue.
Notons qu'il est particulièrement dangereux et probablement sans interêt de dépiler
par bopsPop un élément d'une pile étendue empilé par bopsXpush.
Digression technique : Bops utilise un hash Boph pour se remémorer les données empilées.
Des programmes de test de Bop, par ailleurs inutiles, peuvent servir d'exemples :
Obstacks, chez moi la documentation se trouve sur :
file:/usr/share/doc/glibc-doc/html/libc_3.html#SEC42