The Support Kit: Functions and Macros

This section lists the Support Kit's general-purpose functions, including function-like macros. These functions can be called by programs using any part of the Be operating system.


atomic_add(), atomic_and() , atomic_or()

Declared in: <support/SupportDefs.h>


      int32 atomic_add(int32 *atomicVariable, int32 addValue)
      int32 atomic_and(int32 *atomicVariable, int32 andValue)
      int32 atomic_or(int32 *atomicVariable, int32 orValue)

These functions perform the named operations (addition, bitwise AND, or bitwise OR) on the 32-bit value found in atomicVariable, thus:

   *atomicVariable += addValue
   *atomicVariable &= andValue
   *atomicVariable |= orValue

Each function returns previous value of the int32 variable that atomicVariable points to (in other words, they return the value that was in * atomicVariable before the operation was performed).

The significance of these functions is that they're guaranteed to be atomic: If two threads attempt to access the same atomic variable at the same time (through these functions), one of the two threads will be made to wait until the other thread has completed the operation and updated the atomicVariable value.


beep()

Declared in: <support/Beep.h>


      status_t beep(void) 

Produces the system beep. This function engages the Audio Server, but doesn't wait for the sound to play. If it can't contact the server to play the beep, it returns B_ERROR. If it can't get a satisfactory reply back from the audio server, it returns B_BAD_REPLY. Otherwise, it returns B_OK .

See also: play_sound() in the Media Kit


cast_as() see class_name()


class_name(), is_instance_of() , is_kind_of(), cast_as()

Declared in: <support/ClassInfo.h>


      const char *class_name(object)

      bool is_instance_of(object, class)

      bool is_kind_of(object, class)

      class *cast_as(object, class)

These macros deliver information about an object's type, including the name of its class and its standing in the class hierarchy. In each case, the object argument is a pointer to an object; it can be an object of any type (it doesn't have to descend from any particular class). The class argument is a class name--not a string such as "BApplication", but the type name itself (literally BApplication ).

class_name() returns a pointer to the name of object's class.

is_instance_of() returns true if object is an instance of class, and false otherwise.

is_kind_of() returns true if object is an instance of class or an instance of any class that inherits from class, and false if not.

cast_as() returns a pointer to object cast as a pointer to an object of class, but only if object is a kind of class. If not, object cannot be safely cast as a pointer to class, so cast_as() returns NULL.

For example, given this slice of the inheritance hierarchy from the Interface Kit,

and code like this that creates an instance of the BPictureButton class,

   BButton *anObject = new BPictureButton(...);

the first three macros would work as follows:

      const char *s = class_name(anObject);

      if ( is_instance_of(anObject, BView) )
          printf("The object is an instance of BView.\\n");

      if ( is_kind_of(anObject, BView) )
          printf("The object is a kind of BView.\\n");

Note that class names are not passed as strings, but class_name() returns the name as a string.

The cast_as() macro is most useful when you want to treat a generic object as an instance of a more specific class. Suppose, for example, that the BPictureButton mentioned above becomes the focus view for a window and you retrieve it by calling the BWindow's CurrentFocus() function:

   BView *focus = myWindow->CurrentFocus();

Since the focus view might be any type of view, CurrentFocus() returns a pointer to an object of the base BView class. Unless you know otherwise, you cannot treat the object as anything more specific than a BView instance. However, you can ask the object if it's a kind of BPictureButton and, if it is, cast it to the BPictureButton type:

   if ( is_kind_of(focus, BPictureButton) ) {
       BPictureButton *picbutton = (BPictureButton *)focus);
       if ( picbutton->Behavior() == B_TWO_STATE_BUTTON )
           . . .
   }

The cast_as() macro does the same thing, but more efficiently. It casts the object to the target class if it is safe to do so--if the object is an instance of a class that inherits from the target class or an instance of the target class itself --and returns NULL if not.

   BPictureButton *picbutton = cast_as(focus, BPictureButton);
   if ( picbutton ) {
       if ( picbutton->Behavior() == B_TWO_STATE_BUTTON )
           . . .
   }

cast_as() is often used in place of the cast operator to assure code safety even where an expected result is anticipated and there's no need for an intermediate variable (like focus):

   BPictureButton *picbutton = 
                cast_as(myWindow->CurrentFocus(), BPictureButton);
   if ( picbutton ) {
           . . .
   }

The cast_as() and is_kind_of() macros work alike; they're both based on the C++ dynamic_cast operator and they reflect its behavior. To describe that behavior more precisely, let's adopt the following shorthand terms for an object's type:

Either of these types can be compared to a target type , the type you want to cast the object to or test it against. The target type is the class argument passed to the macros.

In the best of all possible worlds, you'd want to ignore the declared type of an object and compare only the real type to the target type. However, the dynamic_cast operator--and by extension cast_as() and is_kind_of()-- considers the real type only if it has to. It first compares the object's declared type to the target type. It assumes that the declared type is accurate (that the object is truly the kind of object it's represented to be) and it summarily handles the obvious cases: If the target type is the same as the declared type or if it's a class that the declared type inherits from, the operation will succeed. Consequently, cast_as() will cast the object to the target type and is_kind_of() will return true, regardless of the object's real type. In other words, if the target class is above or at the same level as the declared class in the inheritance hierarchy, the real class is ignored.

However, if the declared type doesn't match or derive from the target type, dynamic_cast and the macros look at the real type: If the target class is identical to the real type, or if it's a class that the real type derives from, the operation succeeds. If not, it fails.

Therefore, the is_kind_of() and cast_as() macros will produce reliable results as long as objects are not arbitrarily cast to types that may not be accurate. For example, you should not cast an object to a target type and then attempt to use is_kind_of() to determine if the cast was correct. This code is unreliable:

   BPictureButton *picbutton = 
                       (BPictureButton *)myWindow->CurrentFocus();
   if ( is_kind_of(picbutton, BPictureButton) ) {
           . . .
   }

In this example, is_kind_of() will always return true, no matter what the class of the current focus view. The general rule is that the declared type of an object must always be accurate; an object should be typed only to its own class or to a class that it inherits from. The macros cannot rescue you from an inaccurate cast.


find_instantiation_func()

Declared in: <support/Archivable.h>


      instantiation_func find_instantiation_func(const char *className)
      instantiation_func find_instantiation_func(BMessage *archive)

Returns a pointer to the Instantiate() function that can create instances of the className class, or NULL if the function can't be found. If passed a BMessage archive, find_instantiation_func() gets the name of the class from an entry called "class" in the BMessage.

The instantiation_func type is defined as follows:


      BArchivable *(*instantiation_func) (BMessage *) 

In other words, the function has the same syntax as the Instantiate() function declared in the BArachivable class and replicated in derived classes (with class-specific return values).

The function that's returned can be called like any C function; you don't need the class name or another object of the class. For example:

   instantiation_func func;
   if ( func = find_instantiation_func(arhiveMessage) ) {
       BArchivable *object = func(archiveMessage);
   }

instantiate_object() will do this work for you.

See also: BArchivable::Instantiate() , instantiate_object()


instantiate_object()

Declared in: <support/Archivable.h>


      BArchivable *instantiate_object(BMessage *archive)

Creates and returns a new instance of an archived object, or returns NULL if the object can't be constructed. The object is created by calling the appropriate Instantiate() function for the object recorded in the archive BMessage.

To find the Instantiate() function it should call, instantiate_object() gets the class name of the archived object from the BMessage archive. It takes the first name it finds in an entry called "class". If the class is not part of the loaded image, it looks for an entry named "add_on_signature" for the signature of an add-on image it can load, or an entry named "add_on_path" with the path name of the add-on image. If the signature or path name is found and the file exists, it will load the image and again look for the class definition and Instantiate() function in the new code. If it still can't find the function, instantiate_object() tries other class names in the "class" array, working its way up the class hierarchy. If, after exhausting the class list, it cannot match the archive to an Instantiate() function, it returns NULL.

When successful, instantiate_object() returns the object that Instantiate() created, but typed to the base BArchivable class. The cast_as() macro can type it to a more capable class.

   BArchivable *base = instantiate_object(archive);
   if ( base ) {
       TheClass *object = cast_as(base, TheClass);
       if ( object ) {
           . . .
       }
   }

Because instantiate_object() will look for and load the code needed to run the archived object, it's possible to package an object and deliver it to an application that, until the package arrived, knew nothing of the object or its class.

See also: the BArchivable class, find_instantiation_func()


is_instance_of() see class_name()


is_kind_of() see class_name()


min(), max(), min_c() , max_c()

Declared in: <support/SupportDefs.h>


      min(a, b)
      min_c(a, b)

      max(a, b)
      max_c(a, b)

These macros compare two integers or floating-point numbers. min() and min_c() return the lesser of the two (or b if they're equal); max() and max_c() return the greater of the two (or a if they're equal). min() and max() are not defined for C++ (that is, if __cplusplus is defined), since C++ uses those two names for another purpose. Their identical counterparts, min_c() and max_c(), are defined for all programs.


read_16_swap(), read_32_swap() , write_16_swap(), write_32_swap()

Declared in: <support/SupportDefs.h>


      int16 read_16_swap(int16 *address)
      int32 read_32_swap(int32 *address)

      void write_16_swap(int16 *address, int16 value)
      void write_32_swap(int32 *address, int32 value)

The read...() functions read a 16- or 32-bit value from address, reverse the order of the bytes in the value, and return the swapped value directly.

The write...() functions swap the bytes in the value passed and write the swapped value to address .


validate_instantiation()

Declared in: <support/Archivable.h>


      bool validate_instantiation(BMessage *archive, const char *className)

Returns true if the archive BMessage contains data for an object belonging to the className class, and false if not. The determination is made by looking for the class name in a "class" array in the archive. If the class name appears anywhere in the array, this function returns true. If not, it returns false .


write_16_swap() see read_16_swap()


write_32_swap() see read_16_swap()






The Be Book, HTML Edition, for Developer Release 9 of the Be OS.

Copyright © 1997 Be, Inc. All rights reserved.

Be, the Be logo, BeBox, BeOS, BeWare, and GeekPort are trademarks of Be, Inc.

Last modified