REP: 121
Title: Automatic unloading of libraries for pluginlib
Author: Dirk Thomas
Status: Final
Type: Standards Track
Content-Type: text/x-rst
Created: 6-Feb-2012
ROS-Version: Fuerte
Post-History: 6-Feb-2012

Abstract
========

In REP 116 [1]_ pluginlib was enhance to support unloading
libraries within the life cycle of the ClassLoader.  In this REP
the interface the user of pluginlib uses is revised to better
support the load/create/unload cycle of shared libraries in order to
permit unloading the library from memory when it is no more used.

Current implementation
======================

The ClassLoader of pluginlib exposes the following methods:

* loadLibraryForClass(const std::string& lookup_name)
  Loads the library (if not already loaded) and increments a counter
  which is specific for that library.

* unloadLibraryForClass(const std::string& lookup_name)
  Decrements the counter of that library and unloads the library if
  the counter reaches zero.

These two methods provide a clear interface and semantic regarding
the life cycle of libraries.

In order to instantiate a class from a library the user calls:

* T* createClassInstance(const std::string& lookup_name, bool auto_load = true)
  Creates an instance of type T and returns a pointer.  The ownership
  of the object is transfered to the caller.  If autoloading is
  disabled the pointer might be null if the library has not been
  loaded before.  If autoloading is enabled (default) the library is
  only loaded if it has not been loaded before.

The issue with this implementation is that the user has no indication
if createClassInstance() increased the library counter implicitly or
not.  Furthermore the user has to take care about the correct point
in time when calling unloadLibraryForClass().  If two different
entities are working with the same ClassLoader instance the library
might get unloaded while it is still in use (i.e. A calling
loadLibraryForClass(), B calling createClassInstance(), A calling
unloadLibraryForClass(), results in unloading the library).

Specification
=============

In order to not break existing code which relies on this current
implementation detail the behavior of it can not be changes and is
therefore deprecated (and later on removed).

Instead two new methods are introduced which provide a clear semantic
for creating instances and handling the life cycle of the create
instance.

* boost::shared_ptr<T> createInstance(const std::string& lookup_name)

* T* createUnmanagedInstance(const std::string& lookup_name)

Internally both will always call loadLibraryForClass() which ensures
that the reference counter for the library is increased for every
instance.

For createInstance() the ownership stays with the callee (the 
ClassLoader) and deleting and unloading is triggered by the deleter
of the boost shared pointer.  For createUnmanagedInstance() the
ownership and responsibility to unload the library is transfered to
the caller.

The common usage patterns would be:

* Use createInstance() (once or multiple times) and let the boost
  deleter take care about deleting the instance and unloading the
  library.

or

* Use createUnmanagedInstance() (once or multiple times) and manually
  delete the instance later and call unloadLibraryForClass() for each
  garbaged instance.  This approach is usually used when the
  ownership of the instances should be passed to something else (i.e.
  when using Qt objects).

or

* Wrap multiple create calls between one loadLoadForClass() and
  one unloadLoadForClass() to keep library loaded for a longer time
  (even if no instance are currently loaded).

Backwards Compatibility
=======================

The side effects of the existing and createCreateInstance() method in
combination with unloadLoadForClass() are not fixable without
potentially breaking existing application.  Therefore the
implementation of createClassInstance() is not altered in any way but
deprecated.  The additions will induce no effect on existing code.

The previous option to create an instance with autoloading disabled
is not necessary since that case can be easily queried before and
only conditionally call one of the create methods.

Reference implementation
========================

Reference implementation code is locate in the HG repository.
See the current version of the interface [2]_ and the implementation
[3]_ for detailed information.

References
==========

.. [1] REP 116
   (http://ros.org/reps/rep-0116.html)
.. [2] Patch
   (https://kforge.ros.org/common/pluginlib/file/1e14fef67d09/include/pluginlib/class_loader.h)
.. [3] Patch
   (https://kforge.ros.org/common/pluginlib/file/1e14fef67d09/include/pluginlib/class_loader_imp.h)

Copyright
=========

This document has been placed in the public domain.



..
   Local Variables:
   mode: indented-text
   indent-tabs-mode: nil
   sentence-end-double-space: t
   fill-column: 70
   coding: utf-8
   End: