gawk: Symbol table by cookie

 
 16.4.10.2 Variable Access and Update by Cookie
 ..............................................
 
 A "scalar cookie" is an opaque handle that provides access to a global
 variable or array.  It is an optimization that avoids looking up
 variables in 'gawk''s symbol table every time access is needed.  This
 was discussed earlier, in SeeGeneral Data Types.
 
    The following functions let you work with scalar cookies:
 
 'awk_bool_t sym_lookup_scalar(awk_scalar_t cookie,'
 '                             awk_valtype_t wanted,'
 '                             awk_value_t *result);'
      Retrieve the current value of a scalar cookie.  Once you have
      obtained a scalar cookie using 'sym_lookup()', you can use this
      function to get its value more efficiently.  Return false if the
      value cannot be retrieved.
 
 'awk_bool_t sym_update_scalar(awk_scalar_t cookie, awk_value_t *value);'
      Update the value associated with a scalar cookie.  Return false if
      the new value is not of type 'AWK_STRING', 'AWK_STRNUM',
      'AWK_REGEX', or 'AWK_NUMBER'.  Here too, the predefined variables
      may not be updated.
 
    It is not obvious at first glance how to work with scalar cookies or
 what their raison d'e^tre really is.  In theory, the 'sym_lookup()' and
 'sym_update()' routines are all you really need to work with variables.
 For example, you might have code that looks up the value of a variable,
 evaluates a condition, and then possibly changes the value of the
 variable based on the result of that evaluation, like so:
 
      /*  do_magic --- do something really great */
 
      static awk_value_t *
      do_magic(int nargs, awk_value_t *result)
      {
          awk_value_t value;
 
          if (   sym_lookup("MAGIC_VAR", AWK_NUMBER, & value)
              && some_condition(value.num_value)) {
                  value.num_value += 42;
                  sym_update("MAGIC_VAR", & value);
          }
 
          return make_number(0.0, result);
      }
 
 This code looks (and is) simple and straightforward.  So what's the
 problem?
 
    Well, consider what happens if 'awk'-level code associated with your
 extension calls the 'magic()' function (implemented in C by
 'do_magic()'), once per record, while processing hundreds of thousands
 or millions of records.  The 'MAGIC_VAR' variable is looked up in the
 symbol table once or twice per function call!
 
    The symbol table lookup is really pure overhead; it is considerably
 more efficient to get a cookie that represents the variable, and use
 that to get the variable's value and update it as needed.(1)
 
    Thus, the way to use cookies is as follows.  First, install your
 extension's variable in 'gawk''s symbol table using 'sym_update()', as
 usual.  Then get a scalar cookie for the variable using 'sym_lookup()':
 
      static awk_scalar_t magic_var_cookie;    /* cookie for MAGIC_VAR */
 
      static void
      my_extension_init()
      {
          awk_value_t value;
 
          /* install initial value */
          sym_update("MAGIC_VAR", make_number(42.0, & value));
 
          /* get the cookie */
          sym_lookup("MAGIC_VAR", AWK_SCALAR, & value);
 
          /* save the cookie */
          magic_var_cookie = value.scalar_cookie;
          ...
      }
 
    Next, use the routines in this minor node for retrieving and updating
 the value through the cookie.  Thus, 'do_magic()' now becomes something
 like this:
 
      /*  do_magic --- do something really great */
 
      static awk_value_t *
      do_magic(int nargs, awk_value_t *result)
      {
          awk_value_t value;
 
          if (   sym_lookup_scalar(magic_var_cookie, AWK_NUMBER, & value)
              && some_condition(value.num_value)) {
                  value.num_value += 42;
                  sym_update_scalar(magic_var_cookie, & value);
          }
          ...
 
          return make_number(0.0, result);
      }
 
      NOTE: The previous code omitted error checking for presentation
      purposes.  Your extension code should be more robust and carefully
      check the return values from the API functions.
 
    ---------- Footnotes ----------
 
    (1) The difference is measurable and quite real.  Trust us.