4.10.7.2 Protecting Atoms in Foreign Memory

SICStus Prolog's foreign language interface allows atoms to be passed to foreign functions. When calling foreign functions from Prolog, atoms are passed via the +atom argument type in the predicate specifications of foreign/[2,3] facts. The strings of atoms can be passed to foreign functions via the +string argument type. In the latter case a pointer to the Prolog symbol table's copy of the string for an atom is what is passed. When calling Prolog from C, atoms are passed back from C to Prolog using the -atom and -string argument types in extern/1 declarations. Atoms can also be created in foreign code via functions like SP_atom_from_string().

Prolog does not keep track of atoms (or strings of atoms) stored in foreign memory. As such, it cannot guarantee that those atoms will be retained by atom garbage collection. Therefore SICStus Prolog provides functions to register atoms (or their strings) with the atom garbage collector. Registered atoms will not be reclaimed by the atom garbage collector. Atoms can be registered while it is undesirable for them to be reclaimed, and then unregistered when they are no longer needed.

Of course, the majority of atoms passed as atoms or strings to foreign functions do not need to be registered. Only those that will be stored across foreign function calls (in global variables) or across nested calls to Prolog are at risk. An extra margin of control is given by the fact the programmer always invokes atom garbage collection explicitly, and can ensure that this is only done in contexts that are “safe” for the individual application.

To register or unregister an atom, one of the following functions is used:

     int SP_register_atom(atom)
     SP_atom atom;
     
     int SP_unregister_atom(atom)
     SP_atom atom;

These functions return either SP_ERROR or a non-negative integer. The return values are discussed further in ref-mgc-ago-are.

As noted above, when an atom is passed as a string (+string) to a foreign function, the string the foreign function receives is the one in Prolog's symbol table. When atom garbage collection reclaims the atom for that string, the space for the string will also be reclaimed.

Thus, if the string is to be stored across foreign calls, either a copy of the string or else the atom (+atom) should be passed into the foreign function so that it can be registered and SP_string_from_atom() can be used to access the string from the atom.

Keep in mind that the registration of atoms only pertains to those passed to foreign functions or created in foreign code. Atoms in Prolog's data areas are maintained automatically. Note also that even though an atom may be unregistered in foreign code, atom garbage collection still may not reclaim it as it may be referenced from Prolog's data areas. But if an atom is registered in foreign code, it will be preserved regardless of its presence in Prolog's data areas.

The following example illustrates the use of these functions. In this example the current value of an object (which is an atom) is being stored in a C global variable. There are two C functions that can be called from Prolog, one to update the current value and one to access the value.

     #include <sicstus/sicstus.h>
     
     SP_atom current_object = NULL;
     
     update_object(newvalue)
     SP_atom newvalue;
     {
             /* if current_object contains an atom, unregister it */
             if (current_object)
                     (void) SP_unregister_atom(current_object);
     
             /* register new value */
             (void) SP_register_atom(newvalue);
             current_object = newvalue;
     }
     
     SP_atom get_object()
     {
             return current_object;
     }

Send feedback on this subject.