Boost logo

Boost :

From: Jeremy Pack (rostovpack_at_[hidden])
Date: 2008-07-07 22:42:42


Robert,

> I'm developing a plugin system and I will be loading several DLLs.
> Basically, as far as I know, this means having one factory_map per DLL
> (on Windows).

This depends on how you want to use the factory_maps. Do you want to close
the shared libraries that you aren't using? If not, just use the same
factory_map for every shared library. Unless you have a LOT of separate
shared libraries, this is usually a good solution (if you have a lot, you
may not want the unused libraries taking up RAM).

If you do want to close unused shared libraries, it's a bit trickier. I had
some code that did this, but have let it languish because it didn't cover a
number of special cases. Here is more or less how it worked:

   - Create a counted_factory_map instead of a factory_map. Internally, a
   counted_factory_map contains a separate map and shared_library object for
   each shared library.
   - Whenever you ask it to add a constructor for a class T, it instead adds
   a constructor for a class counted<T> (which is a derived class of T), which
   increments and decrements a counter whenever it is created or destroyed.
   - There is a function in the shared library that can be called to see how
   many objects are currently live from the given shared library.
   - You can call a function on the counted_factory_map to do garbage
   collection - ie, close shared libraries with no live objects.

The reasons this code is not currently used in Extension:

   - It requires a duplicate of almost every class in Extension - a counted
   version and a non-counted version.
   - The counted versions have very high coupling - whereas the uncounted
   versions of shared_library and factory_map are very loosely coupled. It also
   makes it impossible to use parameter_map in its current form.
   - It requires, in the common case, the use of mutexes to protect the
   counters. This requires linking in the Thread library.
   - It only works if all you are doing in a shared library is constructing
   objects using counted_factory. If you take a reference to anything else in a
   shared library, you risk having a dangling reference when all of the
   counted<T> objects are destroyed. Note that this can be alleviated by using
   a separate shared_library instance if you want to do anything besides
   populate a counted_factory_map, since a shared library is only closed when
   all shared_library instances referencing it are destroyed (it is also
   possible to force a shared library to remain open until program termination
   - by passing false as the second parameter to the shared_library
   constructor).

There were a few other special cases that broke it as well - but I can't
remember what they were right now.

I can update that code if people are interested. I certainly wouldn't mind
suggestions about how to avoid some of the problems that I listed, or a
different way of handling this sort of "garbage collection" of unused shared
libraries.

Thanks!

Jeremy Pack


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk