17.4.11.3 Creating and Using Cached Values

The routines in this section allow you to create and release cached values. Like scalar cookies, in theory, cached values are not necessary. You can create numbers and strings using the functions in Constructor Functions. You can then assign those values to variables using sym_update() or sym_update_scalar(), as you like.

However, you can understand the point of cached values if you remember that every string value’s storage must come from gawk_malloc(), gawk_calloc(), or gawk_realloc(). If you have 20 variables, all of which have the same string value, you must create 20 identical copies of the string.111

It is clearly more efficient, if possible, to create a value once, and then tell gawk to reuse the value for multiple variables. That is what the routines in this section let you do. The functions are as follows:

awk_bool_t create_value(awk_value_t *value, awk_value_cookie_t *result);

Create a cached string or numeric value from value for efficient later assignment. Only values of type AWK_NUMBER, AWK_REGEX, AWK_STRNUM, and AWK_STRING are allowed. Any other type is rejected. AWK_UNDEFINED could be allowed, but doing so would result in inferior performance.

awk_bool_t release_value(awk_value_cookie_t vc);

Release the memory associated with a value cookie obtained from create_value().

You use value cookies in a fashion similar to the way you use scalar cookies. In the extension initialization routine, you create the value cookie:

static awk_value_cookie_t answer_cookie;  /* static value cookie */

static void
my_extension_init()
{
    awk_value_t value;
    char *long_string;
    size_t long_string_len;

    /* code from earlier */
    ...
    /* ... fill in long_string and long_string_len ... */
    make_malloced_string(long_string, long_string_len, & value);
    create_value(& value, & answer_cookie);    /* create cookie */
    ...
}

Once the value is created, you can use it as the value of any number of variables:

static awk_value_t *
do_magic(int nargs, awk_value_t *result)
{
    awk_value_t new_value;

    ...    /* as earlier */

    value.val_type = AWK_VALUE_COOKIE;
    value.value_cookie = answer_cookie;
    sym_update("VAR1", & value);
    sym_update("VAR2", & value);
    ...
    sym_update("VAR100", & value);
    ...
}

Using value cookies in this way saves considerable storage, as all of VAR1 through VAR100 share the same value.

You might be wondering, “Is this sharing problematic? What happens if awk code assigns a new value to VAR1; are all the others changed too?”

That’s a great question. The answer is that no, it’s not a problem. Internally, gawk uses reference-counted strings. This means that many variables can share the same string value, and gawk keeps track of the usage. When a variable’s value changes, gawk simply decrements the reference count on the old value and updates the variable to use the new value.

Finally, as part of your cleanup action (see Registering An Exit Callback Function) you should release any cached values that you created, using release_value().


Footnotes

(111)

Numeric values are clearly less problematic, requiring only a C double to store. But of course, GMP and MPFR values do take up more memory.