Chapter Contents

Previous

Next
pool

pool



Allocate a Storage Pool

Portability: SAS/C extension


SYNOPSIS
DESCRIPTION
RETURN VALUE
ERRORS
DIAGNOSTICS
IMPLEMENTATION
EXAMPLE
RELATED FUNCTIONS
SEE ALSO


SYNOPSIS

#include <pool.h>

int pool(POOL_t *p, unsigned eltsize, unsigned initial,
         unsigned extend);


DESCRIPTION

pool creates a storage pool from which elements of a given size can be quickly allocated and freed. The arguments are as follows:
p is a pointer to a POOL_t structure.
eltsize is the size of the elements to be allocated.
initial is the number of elements the pool is to contain initially.
extend is the number by which the pool is extended if all elements are allocated.

If initial is 0, the pool routine computes a convenient initial number of elements. If extend is 0, it is set equal to initial .

In a situation that requires allocation of many items of the same size, using a storage pool is more efficient than using malloc in terms of execution time. It also can be more efficient in terms of storage usage if the initial and extend values are reasonably chosen.


RETURN VALUE

The return value is 1 if a pool is successfully created, or 0 if it is not. If a pool is created, its address and other information is stored in the area addressed by the first argument to pool .


ERRORS

User ABEND 1205 or 1206 may occur if memory management data areas are overlaid.


DIAGNOSTICS

The pool pointer is set to 0 if there is no storage available for the new pool.


IMPLEMENTATION

If an initial size is not specified for a storage pool, space is allocated for seven or more elements, rounded up to fill an integral number of pages.

Under an XA or ESA operating system, memory allocated by pool resides above the 16-megabyte line for programs that run in 31-bit addressing mode.

The initial pool storage, as well as additional storage for extending the pool, is obtained by calling malloc . The performance of palloc and pfree is improved because the frequency of calls to malloc and free is thereby reduced.


EXAMPLE

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pool.h>

#define WORD_LENGTH 24
#define BUFFER_LENGTH 255
#define DELIMITERS " +-*/&=!%^*`~.,;:|?"'{}[]<>()\a\b\f\n\r\t\v"

typedef struct tagLINE {
   struct tagLINE *next;
   int number;
   int count;
   } line_t;

typedef struct tagWORD{
   struct tagWORD *left, *right;
   line_t *first_line, *last_line;
   char token[WORD_LENGTH+1];
   } word_t;

static POOL_t word_pool;
static POOL_t line_pool;
static word_t *word_tree = NULL;

static word_t *alloc_word(const char *);
static line_t *alloc_line(int);
static void add_to_xref(const char *, int);
static word_t *find_word(word_t *, word_t *);
static void add_line(word_t *, int);
static void add_word(word_t **, word_t *);
static void print_xref(word_t *);
static void print_word(word_t *);

   /* Read a file of text, such as this file, from stdin.  Separate   */
   /*  each line of input into tokens.  Write a sorted                */
   /*  "cross-reference" of the file to stdout, having one line for   */
   /*  each distinct token.  For each token, show the line number(s)  */
   /*  on which the token is found.  If the token appears more than   */
   /*  once on a line, show the number of times it appears on that    */
   /*  line.                                                          */
   /*                                                                 */
   /* Here's a sample of the output produced by this program, using   */
   /*  this file as input:                                            */
   /*                                                                 */
   /*  stdin                   : 36, 46, 84, 85(2), 93, 96, 97        */
   /*  stdio                   : 1, 47                                */
   /*  stdlib                  : 3, 48                                */
   /*  stdout                  : 38, 49, 295, 304, 305                */
   /*  storage                 : 50, 107                              */

main()
{
   int success;
   int line_number;
   char input_buffer[BUFFER_LENGTH+2];

      /* Allocate a pool of binary tree elements */
      /* to hold the "words". */
   success = pool(&word_pool, sizeof(word_t), 100, 100);
   if (!success) {
      puts("Can't allocate word pool.");
      exit(4);
   }

      /* Allocate a pool of list elements to hold the */
      /* line numbers.   */
   success = pool(&line_pool, sizeof(line_t), 500, 250);
   if (!success) {
      puts("Can't allocate line count pool.");
      exit(4);
   }

     /* Read each line in the input file.  Pick out tokens */
     /* and add them to the cross-reference tree.          */
   line_number = 0;
   fgets(input_buffer, BUFFER_LENGTH, stdin);
   while (!feof(stdin) && !ferror(stdin)) {
      char *token;
      line_number += 1;
      token = strtok(input_buffer, DELIMITERS);
      while (token) {
         add_to_xref(token, line_number);
         token = strtok(NULL, DELIMITERS);
      }
      fgets(input_buffer, BUFFER_LENGTH, stdin);
   }

   if (ferror(stdin)) {
      puts("Error reading stdin.");
      exit(8);
   }

      /* Print the cross-reference, one word per line.     */
   print_xref(word_tree);

      /* Free the storage pools and exit.                  */
   pdel(&word_pool);
   pdel(&line_pool);

   exit(0);
}

   /* Allocate a new word_t element from the word pool.               */
   /*  Initialize all members and save a copy of the token,           */
   /*  truncating the token if it's longer than WORD_LENGTH.          */
   /*  Exit with an error message if palloc fails.                    */
static word_t *alloc_word(const char *token)
{
   word_t *new_word;

   new_word = (word_t *) palloc(&word_pool);
   if (new_word == NULL) {
      puts("Can't allocate element from word pool");
      exit(12);
   }

   new_word->left = NULL;
   new_word->right = NULL;
   new_word->first_line = NULL;
   new_word->last_line = NULL;
   strncpy(new_word->token, token, WORD_LENGTH);
   new_word->token[WORD_LENGTH] = '\0';

   return new_word;
}

   /* Allocate a new line_t element from the line pool.  Initialize   */
   /*  all members.   Exit with an error message if palloc fails.     */
static line_t *alloc_line(int line_number)
{
   line_t *new_line;

   new_line = (line_t *) palloc(&line_pool);
   if (new_line == NULL) {
      puts("Can't allocate element from line pool");
      exit(12);
   }

   new_line->next = NULL;
   new_line->number = line_number;
   new_line->count = 1;

   return new_line;
}

   /* Add this instance of the word to the cross-reference tree.      */
static void add_to_xref(const char *token, int line_number)
{
   word_t *word, *new_word;

      /* Go ahead and copy the token to a word_t element.             */
   new_word = alloc_word(token);

      /* If the word is already in the tree, free the     */
      /* word_t element we just allocated and add the     */
      /* line number to the word_t element we found.      */
      /* Otherwise, add the new word_t element to the     */
      /* tree and add this line number.                   */
   word = find_word(word_tree, new_word);
   if (word != NULL) {
      pfree(&word_pool, new_word);
      add_line(word, line_number);
   }
   else {
      add_word(&word_tree, new_word);
      add_line(new_word, line_number);
   }

}

   /* Search for the word in the word binary tree.        */
   /* Return NULL if the word is not on the tree.         */
static word_t *find_word(word_t *subtree, word_t *new_word)
{
   word_t *word;

   if (subtree == NULL)
      return NULL;

   word = find_word(subtree->left, new_word);
   if (word != NULL)
      return word;

   if (strcmp(subtree->token, new_word->token) == 0)
      return subtree;

   word = find_word(subtree->right, new_word);
   if (word != NULL)
      return word;

   return NULL;
}

   /* Add an instance of the word for this line.  If      */
   /* the word has already been used on this line,        */
   /* simply increment the count for this line number.    */
   /* Otherwise add a new line_t element for this line    */
   /* number.                                             */
static void add_line(word_t *word, int line_number)
{
   line_t *line;

   if (word->last_line != NULL &&
                            word->last_line->number == line_number)
      word->last_line->count += 1;
   else {
      line = alloc_line(line_number);
      if (word->first_line == NULL)
         word->first_line = line;
      else
         word->last_line->next = line;
      word->last_line = line;
   }

}

   /* Add the new word_t element to the binary tree.                  */
static void add_word(word_t **subtree, word_t *new_word)
{
   int relation;

   if (*subtree == NULL) {
      *subtree = new_word;
      return;
   }

   relation = strcmp((*subtree)->token, new_word->token);
   if (relation > 0)
      add_word(&((*subtree)->left), new_word);
   else if (relation < 0)
      add_word(&((*subtree)->right), new_word);
   else
      abort();                                /* impossible condition */

}

   /* Print a list of the words in alphabetical order.  Beside each   */
   /*  word print the line numbers on which the word appears.  If the */
   /*  word appears more than once on a line, print the line number   */
   /*  followed by a repeat count in parentheses.  For example, if    */
   /*  the word appears twice on line number 20, print "20(2)".       */
static void print_xref(word_t *subtree)
{

   if (subtree != NULL) {
      print_xref(subtree->left);
      print_word(subtree);
      print_xref(subtree->right);
   }

}
   /* Print the line number info for a single word.                   */
static void print_word(word_t *word)
{
   line_t *line;
   char comma;

   printf("%-24s: ", word->token);

   comma = 0;
   for (line = word->first_line; line != NULL; line = line->next) {
      if (comma)
         fputs(", ", stdout);
      comma = 1;
      printf("%d", line->number);
      if (line->count > 1)
         printf("(%d)", line->count);
   }

   putchar('\n');

   if (ferror(stdout)) {
      puts("Error writing to stdout.");
      exit(12);
   }
}


RELATED FUNCTIONS

malloc , palloc , pdel , pfree


SEE ALSO


Chapter Contents

Previous

Next

Top of Page

Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.