10.2. Design

The set of plugins actually used by a given document is usually a very narrow subset of all available plugins. For example, it would be very rare to have a document that contained readers and writers for every external file format supported by K-3D. Many features such as NURBS and image processing are not heavily used at the current time. On Demand Modules take advantage of this by loading a set of module proxies at startup, instead of loading the modules themselves. Each module proxy is an XML file that describes all of the plugin factories for a given module:

 <?xml version="1.0" ?>
 <k3dml package="k3d" version="0.5.0.37" host="i686-pc-mingw32">
   <module name="libk3daqsis.dll" class="00000000 00000000 00000000 00000000">
     <plugins>
       <plugin name="AqsisSurfaceShaderLayer" class="261e244e d82947ba 9e56a9af 03d4cc0f" quality="experimental" type="document">
         <short_description>Encapsulates an Aqsis surface shader layer</short_description>
         <categories>
           <category>Aqsis</category>
         </categories>
         <interfaces>
           <interface>k3d::ri::isurface_shader</interface>
           <interface>k3d::aqsis::isurface_layer</interface>
         </interfaces>
       </plugin>
       <plugin name="AqsisDisplacementShaderLayer" class="1802dce3 71004329 80cbdf0e bc7f142c" quality="experimental" type="document">
         <short_description>Encapsulates an Aqsis displacement shader layer</short_description>
         <categories>
           <category>Aqsis</category>
         </categories>
         <interfaces>
           <interface>k3d::ri::idisplacement_shader</interface>
           <interface>k3d::aqsis::idisplacement_layer</interface>
         </interfaces>
       </plugin>
       <plugin name="Teapot" class="b761f071 f7ed4297 9449028d 2f6236f0" quality="stable" type="document">
         <short_description>Renders a teapot primitive in render engines that support one (Aqsis!)</short_description>
         <categories>
           <category>Aqsis</category>
         </categories>
         <interfaces>
           <interface>k3d::itransform_source</interface>
           <interface>k3d::itransform_sink</interface>
         </interfaces>
       </plugin>
     </plugins>
   </module>
 </k3dml>

Module proxies are automatically generated by the build system using the k3d-make-module-proxy executable.

Each module proxy has the same path and name as the corresponding module, with ".proxy" appended, so a module "k3d-foo.module" will have a proxy "k3d-foo.module.proxy".

Before loading a module at runtime, K-3D checks for the existence of a corresponding proxy file. If the proxy file exists, the application uses it to register a set of plugin factory proxies, which use the serialized XML data to mimic the behavior of the loaded module’s plugin factories. When a caller requests metadata from a plugin factory proxy, it receives the same results it would have received from the "real" plugin factory. When a caller requests instantiation of a plugin, the plugin factory proxy checks to see if the corresponding module has been loaded or not. If not, the module is loaded and the "real" plugin factory is used to complete the request.

Thus, only those plugins that get used have their plugin modules loaded into the application working set - "you don’t pay for what you don’t use". The proxying is transparent to calling code, which does not need to be modified to benefit from the new behavior.

If a proxy isn’t available for a given module, the module is immediately loaded, as has been done in the past. This is useful for a narrow-class of special modules whose capabilities are determined at runtime instead of compile-time.