pfMemory(3pf) OpenGL Performer 3.2.2 libpr C Reference Pages pfMemory(3pf)NAME
pfGetMemoryClassType, pfGetType, pfIsOfType, pfIsExactType,
pfGetTypeName, pfGetMemory, pfGetData, pfRef, pfUnref, pfUnrefDelete,
pfUnrefGetRef, pfGetRef, pfCopy, pfDelete, pfIsFluxed, pfCompare,
pfPrint, pfMalloc, pfCalloc, pfRealloc, pfFree, pfGetArena, pfGetSize,
pfGetMemoryArenaBytesUsed, pfStrdup - Reference, copy, delete, print and
query pfMemory
FUNCTION SPECIFICATION
#include <Performer/pf.h>
pfType * pfGetMemoryClassType(void);
pfType * pfGetType(const void *ptr);
int pfIsOfType(const void *ptr, pfType *type);
int pfIsExactType(const void *ptr, pfType *type);
const char * pfGetTypeName(const void *ptr);
pfMemory * pfGetMemory(const void *ptr);
void * pfGetData(const void *ptr);
int pfRef(void *ptr);
int pfUnref(void *ptr);
int pfUnrefDelete(void *ptr);
int pfUnrefGetRef(void *ptr);
int pfGetRef(const void *ptr);
int pfCopy(void *dst, void *src);
int pfDelete(void *ptr);
int pfIsFluxed(void *ptr);
int pfCompare(const void *ptr1, const void *ptr2);
void pfPrint(const void *ptr, uint which, uint verbose,
FILE *file);
void * pfMalloc(size_t nbytes, void *arena);
void * pfCalloc(size_t numelem, size_t elsize, void *arena);
Page 1
pfMemory(3pf) OpenGL Performer 3.2.2 libpr C Reference Pages pfMemory(3pf)
void * pfRealloc(void *ptr, size_t nbytes);
void pfFree(void *ptr);
void * pfGetArena(void *ptr);
size_t pfGetSize(void *ptr);
int pfGetMemoryArenaBytesUsed();
char * pfStrdup(const char *str, void *arena);
DESCRIPTION
pfMemory is the base class from which all major OpenGL Performer classes
are derived and is also the type used by the OpenGL Performer memory
allocation routines such as pfMalloc and pfFree.
Because most OpenGL Performer data structures are derived from pfMemory,
they inherit the functionality of the pfMemory routines described here.
In practice this means you can use the pfMemory routines listed above
with most any OpenGL Performer object, such as pfMaterial, pfList, pfFog,
pfFrustum, pfChannel, pfGroup, pfGeode or with a data pointer returned by
pfMalloc.
pfMemory supports the following:
1. Typed data structures.
2. Memory arena allocation.
3. Memory chunks which know their size.
4. Reference counting.
with only a 4 word overhead.
Although the OpenGL Performer general memory allocation routines (-
pfMalloc) create pfMemories, they return void* so the application can
treat the allocation as raw data. Consequently, all routines that would
normally take a pfMemory* take a void* and infer the pfMemory handle so
that applications can treat pfMemory as raw memory. However, one caveat
is that routines which take raw memory such as pfGSetAttr or pfFree
should not be passed a pointer to static data since the routines may not
be able to successfully infer the pfMemory handle from the void*.
--------------- <------ pfMemory*
| pfMemory |
| header |
| |
--------------- <------ void* returned by
| | allocation routines
Page 2
pfMemory(3pf) OpenGL Performer 3.2.2 libpr C Reference Pages pfMemory(3pf)
| raw data |
. .
. .
. .
| |
---------------
Routines which convert between pfMemory* and void* are:
void* -> pfMemory*: pfGetMemory
pfMemory* -> void*: pfGetData
Note that is it legal to pass either a pfMemory* or a void* to those
routines which are prototyped as accepting a void*, e.g., pfRef. In this
way, a single set of routines supports the same feature set including
reference counts, copy, and delete for pfMemories used as OpenGL
Performer data types like pfGeoSet as well as for pfMemories used as raw
data like pfGeoSet attribute arrays.
pfGetMemoryClassType returns the pfType* for the class pfMemory. The
pfType* returned by pfGetMemoryClassType is the same as the pfType*
returned by invoking pfGetType on any instance of class pfMemory.
Because OpenGL Performer allows subclassing of built-in types, when
decisions are made based on the type of an object, it is usually better
to use pfIsOfType to test if an object is of a type derived from a
Performer type rather than to test for strict equality of the pfType*'s.
All objects derived from pfMemory have a type identifier (pfType*) that
is returned by pfGetType
Example 1: API sharing.
dcs = pfNewDCS();
/* pfDCS uses pfGroup routine */
pfAddChild(dcs, geode);
/* pfDCS uses pfNode routine */
pfNodeTravMask(dcs, PFTRAV_ISECT, DCS_MASK, PFTRAV_SELF | PFTRAV_DESCEND, PF_SET);
Each data type derived from pfMemory has an associated routine for
getting a pointer to its corresponding pfType, e.g. pfGetDCSClassType()
returns the pfType* corresponding to the pfDCS class. The exact type of
an object is tested by comparing its pfType* to that returned by one of
these pfGet<*>ClassType routines or with the pfIsExactType test, e.g.
Page 3
pfMemory(3pf) OpenGL Performer 3.2.2 libpr C Reference Pages pfMemory(3pf)
if (pfGetType(obj) == pfGetGroupClassType()) ...
if (pfIsExactType(obj, pfGetGroupClassType())) ...
But since OpenGL Performer allows subclassing and the creation of new
types in C++, it's more often desirable to know whether a particular
object is of a type derived from a particular type defined by OpenGL
Performer. In particular, exact type tests makes application code more
likely to fail on scene graphs produced by database loaders that use
subclassing. pfIsOfType performs this test and returns TRUE if mem's
type is derived from type:
if (pfIsOfType(obj, pfGetGroupClassType())) ...
If 'obj' is a pfDCS, then the above conditional would evaluate TRUE since
pfDCS is derived from pfGroup.
pfGetTypeName returns a string that identifies the type of mem. For
example, if mem is a pfDCS, the string returned is "pfDCS".
All pfMemories have a reference count which indicates how many times the
pfMemory is referenced, either by other pfMemories or by the application.
Reference counts are crucial for many database operations, particularly
deletion, since it is highly dangerous to delete a pfMemory which is
still being used, i.e., its reference count is greater than 0.
Reference counts may be incremented and decremented by pfRef and pfUnref
respectively. pfGetRef returns the reference count of mem.
pfUnrefGetRef decrements the reference count and returns the new value,
as an atomic operation, i.e. it is guaranteed that no other process can
change the value or free the memory between the decrement and the time
the value is read. pfUnrefDelete will decrement the reference count of
mem and delete it if the count is <= 0. Thus it is equivalent to calling
pfUnref followed by pfDelete, as an atomic operation.
pfDelete frees the memory associated with mem if its reference count is
<= 0. When an object is freed, it decrements the reference count of all
pfMemories that it once referenced and will delete any of these
pfMemories with reference counts that are <= 0. Thus, pfDelete will
follow all reference chains until it encounters a pfMemory which it
cannot delete. Note that the reference count of a pfNode is incremented
each time it is added as a child to a pfGroup. Thus, a pfNode must be
removed from all its parents before it can be deleted.
When multiprocessing in a libpf application, pfNodes should be pfDeleteed
only in the APP or DBASE processes as should libpr objects that are
referenced directly or indirectly by pfNodes, like pfGeoSets and
pfGeoStates. If you wish to delete objects in processes other than the
Page 4
pfMemory(3pf) OpenGL Performer 3.2.2 libpr C Reference Pages pfMemory(3pf)
APP or DBASE, use pfAsyncDelete.
Example 2: Deletion
pfMaterial *mtl;
pfTexture *tex;
pfGeoState *brickStyle, *woodStyle;
pfGeoSet *brickWall, *woodWall;
mtl = pfNewMtl(arena);
brickStyle = pfNewGState(arena);
tex = pfNewTex(arena);
pfLoadTexFile(tex, "brick.rgb");
pfGStateAttr(brickStyle, PFSTATE_TEXTURE, tex);
pfGStateAttr(brickStyle, PFSTATE_FRONTMTL, mtl);
woodStyle = pfNewGState(arena);
tex = pfNewTex(arena);
pfLoadTexFile(tex, "wood.rgb");
pfGStateAttr(woodStyle, PFSTATE_TEXTURE, tex);
pfGStateAttr(woodStyle, PFSTATE_FRONTMTL, mtl);
brickWall = pfNewGSet(arena);
pfGSetGState(brickWall, brickStyle);
pfGSetAttr(brickWall, PFGS_COORD3, PFGS_PER_VERTEX, coords);
woodWall = pfNewGSet(arena);
pfGSetAttr(woodWall, PFGS_COORD3, PFGS_PER_VERTEX, coords);
pfGSetGState(woodWall, woodStyle);
pfDelete(woodWall);
/* At this point woodWall, woodStyle, and the wood texture
* have been deleted. coords and mtl have not been deleted
* since they are referenced by brickWall and brickStyle respectively.
*/
pfDelete returns the following:
FALSE mem was not deleted
TRUE mem was deleted
-1 mem is not a pfMemory
pfDelete is implemented for all OpenGL Performer objects except the
following:
pfPipe
Page 5
pfMemory(3pf) OpenGL Performer 3.2.2 libpr C Reference Pages pfMemory(3pf)
pfChannel
pfEarthSky
pfBuffer
pfPipeWindow
pfTraverser
pfState
pfDataPool
pfIsFluxed returns TRUE if a pfMemory is actually the data portion of a
pfFluxMemory that is part of a pfFlux. It returns FALSE otherwise.
Calling pfRef, pfUnref, pfUnrefDelete, pfUnrefGetRef, pfGetRef, or
pfDelete on a Fluxed pfMemory, will actually call the function on the
parent pfFlux.
pfCopy copies src into dst. pfCopy is not recursive - it does not follow
reference chains but instead copies only the first- level references. The
reference counts of objects newly referenced by dst are incremented by
one while those counts of objects previously reverenced by dst are
decremented by one. Objects whose reference counts reach 0 during pfCopy
are not deleted. A value of TRUE will be returned if the copy
successfully completes and FALSE will be returned if an error is
encountered. If the destination object is a growable object (such as a
pfList) then it will automatically grow as needed and as memory permits
to hold the copy of the source object. If the destination object is not
a growable object and the src object is larger than the destination
object, no copy will be done and a value of FALSE will be returned.
pfCopy is currently not implemented for any libpf data structures and is
not implemented for the following libpr data structures:
pfState
pfDataPool
pfCompare compares the object p1 to the object p2. If the objects are
identical, a value of 0 will be returned. Upon the first difference, a
value of (1) will be returned if p1 had a greater value and a value of
(-1) will be returned if p2 had a greater value. pfCompare is recursive
on known defined objects and their sub objects but is not recursive on
user data or generic buffers or lists that hold undefined data. Derived
classes first compare their parent classes. If objects of different
types are compared, they will be found to be different and the return
value will be based on a comparison of the p1 and p2 pointer values.
Page 6
pfMemory(3pf) OpenGL Performer 3.2.2 libpr C Reference Pages pfMemory(3pf)
pfPrint Prints information to a file about the specified pfMemory mem.
The file argument specifies the file. If file is NULL, the listing is
printed to stderr. pfPrint takes a verbosity indicator, verbose. Valid
selections in order of increasing verbosity are:
PFPRINT_VB_OFF no printing
PFPRINT_VB_ON minimal printing (default)
PFPRINT_VB_NOTICE minimal printing (default)
PFPRINT_VB_INFO considerable printing
PFPRINT_VB_DEBUG exhaustive printing
If mem is a type of pfNode, then which specifies whether the print
traversal should only traverse the current node (PFTRAV_SELF) or print
out the entire scene graph rooted by node mem by traversing node and its
descendents in the graph (PFTRAV_SELF | PFTRAV_DESCEND). If mem is a
pfFrameStats, then which specifies a bitmask of frame statistics classes
that should be printed. If mem is a pfGeoSet, then which is ignored and
information about that pfGeoSet is printed according to the verbosity
indicator. The output contains the types, names and bounds of the nodes
and pfGeoSets in the hierarchy. This routine is provided for debugging
purposes only and the content and format may change in future releases.
Example 3: Print entire contents of a pfGeoSet, gset, to stderr.
pfPrint(gset, NULL, PFPRINT_VB_DEBUG, NULL);
Example 4: Print entire scene graph under node to a file file with
default verbosity.
file = fopen ("scene.out","w");
pfPrint(scene, PFTRAV_SELF | PFTRAV_DESCEND, PFPRINT_VB_ON, fp);
fclose(file);
Example 5: Print select classes of a pfFrameStats structure, stats, to
stderr.
pfPrint(stats, PFSTATS_ENGFX | PFFSTATS_ENDB | PFFSTATS_ENCULL, PFSTATS_ON, NULL);
pfMalloc and the related routines provide a consistent method to allocate
memory, either from the user's heap (using the C-library malloc function)
or from a shared memory arena (using the IRIX amalloc function). In
addition, these routines provide a reference counting mechanism used by
OpenGL Performer to efficiently manage memory.
pfMalloc operates identically to the C-library malloc function, except
that a shared memory arena may be specified to allocate the memory from.
Page 7
pfMemory(3pf) OpenGL Performer 3.2.2 libpr C Reference Pages pfMemory(3pf)
If arena is NULL, memory is allocated from the heap, otherwise memory is
allocated from arena which must be a previously configured shared memory
arena (see pfSharedMem).
Shared memory arenas can be created using acreate and can be found by
using pfGetSharedArena.
pfCalloc and pfRealloc function just as their Unix counterparts, except
that they may use shared arenas.
In all cases, a pointer to the allocated memory block is returned or NULL
if there is not enough available memory.
The data pointer returned by pfMalloc, pfCalloc, and pfRealloc is
actually part of a pfMemory object that, among other things, provides a
reference count. Reference counts are used to keep track of how many
times each allocated block of memory is referenced or instanced. All
OpenGL Performer libpr objects (pfMemory) are created with pfMalloc so
their reference counts are updated by appropriate libpr routines.
Examples of references follow:
Example 6:
tex = pfNewTex(NULL);
/* Attach 'tex' to gstate0 and gstate1 */
pfGStateAttr(gstate0, PFSTATE_TEXTURE, tex);
pfGStateAttr(gstate1, PFSTATE_TEXTURE, tex);
/* The reference count of 'tex' is now 2 */
/* Remove 'tex' from gstate1 */
pfGStateAttr(gstate1, PFSTATE_TEXTURE, NULL);
/* The reference count of 'tex' is now 1 */
Example 7:
coords = (pfVec3*) pfMalloc(sizeof(pfVec3) * numVerts, arena);
/* Attach 'coords' to non-indexed pfGeoSet, 'gset' */
pfGSetAttr(gset, PFGS_COORD3, PFGS_PER_VERTEX, coords, NULL);
/* The reference count of 'coords' is now 1 */
Page 8
pfMemory(3pf) OpenGL Performer 3.2.2 libpr C Reference Pages pfMemory(3pf)
Example 8:
/* Attach 'gstate0' to 'gset' */
pfGSetGState(gset, gstate0);
/* The reference count of 'gstate0' is now incremented by 1 */
pfFree frees the memory associated with ptr. It is an error to pfFree
memory that was not allocated by pfMalloc, pfCalloc, or pfRealloc. It is
also an error to use any method other than pfFree or pfDelete to free
memory allocated by pfMalloc, pfCalloc, or pfRealloc.
pfFree does not honor the reference count of ptr. This means that you
can free a chunk of memory that is still being used (which means that its
reference count is > 0) with potentially disastrous results. Typical
failure modes are in the form of mysterious memory corruption and
segmentation violations.
pfDelete, however, does honor the reference count of ptr and will not
delete any memory whose reference count is > 0. pfDelete returns -1 if
ptr is not a pfMalloc pointer, TRUE if ptr was deleted, and FALSE
otherwise. pfDelete is recommended if you are not sure of the reference
count of a piece of memory. See the pfObject reference page for more
details on pfDelete.
pfGetArena returns the arena pointer which ptr was allocated from or NULL
if ptr was allocated from the process heap.
pfGetSize returns the size in bytes of the memory referenced by ptr or 0
if ptr is not a pfMalloc pointer.
pfGetMemoryArenaBytesUsed returns the number of bytes currently allocated
from the shared arena. It takes into account all the Performer calls
that allocate or free shared arena memory (pfMalloc, pfCalloc, pfRealloc,
pfDelete, pfFree, new on any Performer class, etc). This call is only
available in the DEBUG libraries. It is meant for debugging memory leaks
and therefore is not necessary in the optimized libraries. If called with
optimized libraries, it returns (-1). This call makes it easier to
distinguish between memory leaks and memory fragmentation: If the arena
grows but the number of bytes used doesn't then the program in question
causes memory fragmentation but doesn't leak.
pfStrdup duplicates the NULL-terminated string str by allocating storage
in the shared memory arena defined by the arena argument.
BUGS
pfPrint is not yet implemented for pfGeoStates and other state
structures, and is not implemented for pfPaths or pfLists.
Page 9
pfMemory(3pf) OpenGL Performer 3.2.2 libpr C Reference Pages pfMemory(3pf)SEE ALSO
acreate, calloc, free, malloc, realloc, pfInitArenas
Page 10