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