ObjectStore C++ API Reference

Chapter 5

User-Supplied Functions

Access to database services sometimes requires support from user-defined functions. The required functions are listed alphabetically in this chapter.

Function

Discriminant Functions

For each union-valued data member of each persistently allocated class, ObjectStore requires that the user provide an associated discriminant function, which indicates the field of the union currently in use. The function is used by the system at run time, when a union is brought into virtual memory from persistent storage. The discriminant function is a member function of the class defining the union-valued data member.

Similarly, for each union that is not a data member value, ObjectStore requires that the user provide a discriminant function. In this case, the discriminant function must be a member function of the union itself.

Each discriminant function is declared as follows:

      os_int32  function-name();
The type os_int32 is defined as either int or long. The value returned is an integer indicating the union's active field (1 for the first field, 2 for the second, and so on). A return value of 0 indicates an uninitialized union.

For a data member whose value is a vector of unions, a discriminant function of the same form is also required. Its return value indicates the active field of each of the vector's elements. (At a given time, all vector elements must have the same field as the active one.)

Note that a discriminant function cannot be virtual.

Each discriminant function's name serves to associate it with a union or vector of unions. The function name has the following form:

      discriminant[_ union-name[_ data-member-name]]
where union-name is the name of the associated union, and data-member-name is the name of the associated data member. The union name and data member name can be dropped if no ambiguity results. The data member name can be omitted when the class defining the discriminant function contains exactly one data member of the type. The union name can be omitted when the class defining the discriminant function contains exactly one union data member. The union name is actually redundant when the data member name is specified, but it is retained so that the discriminant function is self-documenting.

Discriminant functions are restricted with regard to the computations they can perform. Each discriminant member function of a given class must not reference data members other than those nonstatic members defined by that class and its nonvirtual bases. In addition, each such function must not rely on any global program state, perform any operations on pointers except comparison against 0, or invoke any virtual functions.

In addition, when accessing databases created by clients with a different byte ordering, access to a data member whose value occupies more than a single byte must be mediated by objectstore::discriminant_swap_bytes(). This function performs byte swapping that ObjectStore normally performs automatically. Use of this function is only required within discriminant functions; it is an error to invoke it in any other context. This function is declared as follows:

      static void discriminant_swap_bytes(
char *address, char *result, os_int32 n_bytes) ;
The address argument is the address of the member whose access is being mediated by this function. The n_bytes argument is the number of bytes to swap; possible values are 2, 4, and 8. The result argument points to memory allocated by the user to hold the correctly byte-swapped result; the allocated space should contain n_bytes bytes.

Below is a sample declaration of a class with a data member whose value is a union.

struct kgraph {
      typedef os_int32 tag_type
      char kg_type;
      union kg_union {
            struct kgraph *kg_kg;
            os_int32 kg_int;
      } kg;
      os_int32 discriminant(); // discriminant function for kg
};
os_int32 kgraph::discriminant()
{
      tag_type val;
      if (sizeof (tag_type)>1)
            // swap bytes for tags larger than char
            objectstore::discriminant_swap_bytes((char*)&kgtype,
                  (char*)&val,
                  sizeof(tag_type));
      else
            val = kgtype;
      return val;
}
If the value returned by the discriminant function is larger than the number of alternatives for the union, an exception such as the following is displayed:

No handler for exception:
Union discriminant function return value was out of bounds 
<err-0025-0729>Union discriminant function returned a value larger than 
the number of alternatives for data member kgraph.kg<0> of class 
kgraph.
...
See Appendix A, Exception Facility for information about this exception.

At run time, when type determination is deemed necessary, the discriminant function is invoked. This function could have been named discriminant_kg_union or discriminant_kg_union_kg.



[previous] [next]

Copyright © 1997 Object Design, Inc. All rights reserved.

Updated: 03/31/98 17:33:01