gawk: Symbol table by cookie

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