The IModule Subclass Method Implementations
methods for the new IModule class are just like any other AddRef
, so they're not shown here. The FreeResources
is an empty function, too, since there's no special file or memory allocation on a per-module basis that needs to be tidied up.
What remains is CreateInstance, the method BREW invokes in the module to obtain class instances from the module. It's what calls the class' AEEClsCreateInstance function. The module's CreateInstance functionm must do the same work as the existing IModule's CreateInstance as well as enforce the singleton contract (see Listing 2).
The function shown in Listing 2 has two jobs: to enforce the singleton contract and to create the singleton instance if one is not already available. The code is quite straightforward. On entry, if the module is being asked for an instance of the singleton class and the module's pInstance member has a pointer to the singleton class, it simply increments the reference count for the existing object and returns it. This guarantees that any client of the module always receives the same instance of the object. Otherwise, it creates the object in the usual way, either by calling the static-compiled factory method if one was handed to AEEStaticMod_Load, or by invoking your AEEClsCreateInstance (which is the usual case).
The rest of the singleton extension is coded just like any other extension: its entry point is CreateInstance, and it is responsible for building the public interface with its virtual table structure, and private data structure that's cast-compatible with the public structure.
As you can see, it's easy to create a module that can implement the singleton contract for one or more of its classes. While the example I show demonstrates a single class, you can extend this easily by adding additional slots in the module's data for each singleton class instance, then adding the appropriate enforcement in your module's CreateInstance method.
In addition to allowing you create singletons, the knowledge that the IModule instance for your module is only created once gives you the opportunity to share other data between class instances. This gives you an effective way to create variables with class-wide scope. The possibilities for this are virtually limitless, from sharing data between class instances to pooling shared resources for compression or other algorithms.