Caching Objects

When an object is cached, the same interface pointer is always returned by the IDirectMusicLoader::GetObject method.

Caching is used extensively in the file loading process to resolve links to objects. If an object is not found in the cache, it has to be reloaded, even if it already exists. For example, two segments could reference the same style. When the first segment loads, it calls the loader to get the style, which in turn creates a style object, loads it from disk, stores a pointer to the style in the cache, and returns it to the segment. If caching is enabled, when the second segment loads it asks for the style and the loader immediately returns it, so both segments point to the same style. If caching is disabled, the second segment's request for the style results in a duplicate style loaded from the file. This is very inefficient.

Another example: IDirectMusicBand counts on the loader to keep the General MIDI DLS collection cached. Every time it comes across a GM instrument, it gets the collection from the loader by requesting it with GUID_DefaultGMCollection. If caching for CLSID_DirectMusicCollection is disabled, every patch change in a MIDI file will result in a separate copy of the entire GM collection being created—not good.

By default, caching is enabled for all object classes. You can disable caching for an object class, or for all objects, by using the IDirectMusicLoader::EnableCache method. This method can also be used to re-enable caching for any or all object classes.

If you wish to clear the cache without disabling future caching, use the IDirectMusicLoader::ClearCache method.

To cache a single object, pass it to the IDirectMusicLoader::CacheObject method. You can remove it from the cache, ensuring that it will be loaded again on the next call to GetObject, by using the IDirectMusicLoader::ReleaseObject method.

It is a good idea to call ReleaseObject on a cached object, particularly a segment, before destroying the object by calling its own Release method. If you don't do this, a copy of the object remains in the cache along with certain state information. In the case of a segment, any instance you later create will be loaded from the cache, and its start point and loop points will be the same as they were when the previous instance was destroyed.

With judicious use of CacheObject, ReleaseObject, and EnableCache, you can have the objects you don't need released, while others remain in the cache.