gawk: Cached values

1 
1 16.4.10.3 Creating and Using Cached Values
1 ..........................................
1 
1 The routines in this minor node allow you to create and release cached
1 values.  Like scalar cookies, in theory, cached values are not
1 necessary.  You can create numbers and strings using the functions in
1 ⇒Constructor Functions.  You can then assign those values to
1 variables using 'sym_update()' or 'sym_update_scalar()', as you like.
1 
1    However, you can understand the point of cached values if you
1 remember that _every_ string value's storage _must_ come from
1 'gawk_malloc()', 'gawk_calloc()', or 'gawk_realloc()'.  If you have 20
1 variables, all of which have the same string value, you must create 20
1 identical copies of the string.(1)
1 
1    It is clearly more efficient, if possible, to create a value once,
1 and then tell 'gawk' to reuse the value for multiple variables.  That is
1 what the routines in this minor node let you do.  The functions are as
1 follows:
1 
1 'awk_bool_t create_value(awk_value_t *value, awk_value_cookie_t *result);'
1      Create a cached string or numeric value from 'value' for efficient
1      later assignment.  Only values of type 'AWK_NUMBER', 'AWK_REGEX',
1      'AWK_STRNUM', and 'AWK_STRING' are allowed.  Any other type is
1      rejected.  'AWK_UNDEFINED' could be allowed, but doing so would
1      result in inferior performance.
1 
1 'awk_bool_t release_value(awk_value_cookie_t vc);'
1      Release the memory associated with a value cookie obtained from
1      'create_value()'.
1 
1    You use value cookies in a fashion similar to the way you use scalar
1 cookies.  In the extension initialization routine, you create the value
1 cookie:
1 
1      static awk_value_cookie_t answer_cookie;  /* static value cookie */
1 
1      static void
1      my_extension_init()
1      {
1          awk_value_t value;
1          char *long_string;
1          size_t long_string_len;
1 
1          /* code from earlier */
1          ...
1          /* ... fill in long_string and long_string_len ... */
1          make_malloced_string(long_string, long_string_len, & value);
1          create_value(& value, & answer_cookie);    /* create cookie */
1          ...
1      }
1 
1    Once the value is created, you can use it as the value of any number
1 of variables:
1 
1      static awk_value_t *
1      do_magic(int nargs, awk_value_t *result)
1      {
1          awk_value_t new_value;
1 
1          ...    /* as earlier */
1 
1          value.val_type = AWK_VALUE_COOKIE;
1          value.value_cookie = answer_cookie;
1          sym_update("VAR1", & value);
1          sym_update("VAR2", & value);
1          ...
1          sym_update("VAR100", & value);
1          ...
1      }
1 
1 Using value cookies in this way saves considerable storage, as all of
1 'VAR1' through 'VAR100' share the same value.
1 
1    You might be wondering, "Is this sharing problematic?  What happens
1 if 'awk' code assigns a new value to 'VAR1'; are all the others changed
1 too?"
1 
1    That's a great question.  The answer is that no, it's not a problem.
1 Internally, 'gawk' uses "reference-counted strings".  This means that
1 many variables can share the same string value, and 'gawk' keeps track
1 of the usage.  When a variable's value changes, 'gawk' simply decrements
1 the reference count on the old value and updates the variable to use the
1 new value.
1 
11    Finally, as part of your cleanup action (⇒Exit Callback
 Functions) you should release any cached values that you created,
1 using 'release_value()'.
1 
1    ---------- Footnotes ----------
1 
1    (1) Numeric values are clearly less problematic, requiring only a C
1 'double' to store.  But of course, GMP and MPFR values _do_ take up more
1 memory.
1