3.13 Memory Management

WOSA/XFS specifies a protocol for dynamic allocation and release of memory. The general strategy is that the service providers allocate memory as they need it, and the applications specify when it can be released. This is implemented using a standard structure (WFSRESULT, defined in Section 8.1) that is always used to pass information to the applications from the services.

Most service provider function calls are asynchronous, and return their results via a completion message, which contains a pointer to a WFSRESULT structure, containing the function return status (hResult) and optional data. The service provider allocates the memory for this structure, using the memory management framework described below. The deallocation of the structure is done as follows:

Four functions are provided by the XFS Manager to implement this protocol: WFMAllocateBuffer, WFMAllocateMore, WFMFreeBuffer, and WFSFreeResult. Using these functions, two widely applicable allocation policies are supported:

Linear allocation can be used for any flat or contiguously allocated data structure. Such structures are returned in a single block of allocated memory by the WFMAllocateBuffer function.

Linked allocation can be used as an efficient way of managing complex data structures, permitting the service provider some flexibility while allowing the application to release the entire structure with a single call. In cases in which the service provider does not know a priori the size of the result data set, it makes an initial estimate, and uses WFMAllocateBuffer. If the service provider later determines that more space is required by the data, new memory is requested using the function WFMAllocateMore, and is automatically linked to the originally allocated block. The new memory block returned by WFMAllocateMore is, in general, not contiguous with the root block, and the user of this function should behave in all circumstances as if it is not.

The service provider is free to choose whatever allocation granularity is most convenient. This is completely transparent to the application or XFS Manager, which frees the entire WFSRESULT structure with a single WFSFreeResult call (the XFS Manager can also use this call as an indication that it can clean up any other objects associated with the request). Applications must be sure always to free a returned WFSRESULT structure. Note that a WFSRESULT structure may be returned even if the service provider has returned an error; if no WFSRESULT is returned, the pointer to the structure is NULL. A service provider may use also this facility for its "private" memory management requirements; it then uses the WFMFreeBuffer support function to free the allocated memory.

NOTE:

Applications and service providers must use the facilities provided by the XFS Manager for XFS-related memory allocation and deallocation, in order to avoid memory management conflicts among the applications, the XFS Manager and the service providers.

The following example illustrates how a service provider dynamically allocates a WFSRESULT buffer structure and an additional data buffer. Note that WFMAllocateMore automatically links these, allowing the application to free both structures with a single call.

WFSRESULT * lpResultBuffer;

// service provider allocates a WFSResult buffer structure

result = WFMAllocateBuffer(sizeof(WFSRESULT), ulMemFlags, &lpResultBuffer);
· 
· 
· 
// service provider allocates additional memory 

hr = WFMAllocateMore(evenMoreMemory, lpResultBuffer, &lpResultBuffer->lpBuffer);
· 
· 
· 

Once the application has retrieved all the information it needs from the WFSRESULT buffer and any associated structures, it must free the memory, which requires only a single call:

// application deallocates the structure when it is finished with it

hr = WFSFreeResult(lpResultBuffer); // frees both the result buffer and              // any additional buffers

NOTE:

When an application invokes an asynchronous or immediate (i.e., non-blocking) function which takes a pointer to a memory object as an argument, it is the responsibility of the service provider to ensure that it no longer needs access to the object before returning control to the application. This allows the application to release (deallocate) the memory object immediately upon the return from the call.