From 273ce670f433c5d4aee6cd889d4fc8a0c3a0ef1d Mon Sep 17 00:00:00 2001
From: Florent Lamiraux <florent@laas.fr>
Date: Mon, 20 Jun 2011 17:09:02 +0200
Subject: [PATCH] FactoryStorage and PoolStorage are now singletons.

    g_pool and g_factory global variables have been replaced by static methods
    getInstance in each class.
    getInstance returns a pointer to the unique instance of the class and
    creates it if needed.
---
 doc/additionalDoc/package.h     |  9 +++---
 include/dynamic-graph/entity.h  |  2 +-
 include/dynamic-graph/factory.h | 45 ++++++++++++----------------
 include/dynamic-graph/pool.h    | 23 ++++++++-------
 src/dgraph/entity.cpp           |  4 +--
 src/dgraph/factory.cpp          | 23 ++++++++++++---
 src/dgraph/pool.cpp             | 23 +++++++++++----
 src/traces/tracer.cpp           |  4 +--
 tests/factory.cpp               | 52 +++++++++++++++++++--------------
 tests/pool.cpp                  | 12 +++++---
 10 files changed, 114 insertions(+), 83 deletions(-)

diff --git a/doc/additionalDoc/package.h b/doc/additionalDoc/package.h
index 1137875..3933783 100644
--- a/doc/additionalDoc/package.h
+++ b/doc/additionalDoc/package.h
@@ -112,11 +112,10 @@ Some basic shell functions, and support for procedures, are also included.
 For a complete list of those, load the plugin shell-functions.so and type 'help'
 at the command line.
 
-The public static objects (singletons) made available by including the
-corresponding headers in this module are:
-\li g_factory: dynamicgraph::FactoryStorage
-\li g_pool: dynamicgraph::PoolStorage
-\li g_shell: dynamicgraph::Interpreter
+The (singletons made available by including the corresponding headers in this
+module are:
+\li dynamicgraph::FactoryStorage
+\li dynamicgraph::PoolStorage
 
 For an example of a program creating entities in C++, see the unit test
 test_pool.cpp (in your package source directory/unitTesting).
diff --git a/include/dynamic-graph/entity.h b/include/dynamic-graph/entity.h
index 601a25b..dde3226 100644
--- a/include/dynamic-graph/entity.h
+++ b/include/dynamic-graph/entity.h
@@ -64,7 +64,7 @@ namespace dynamicgraph
   ///
   /// These signals link the entities together to form a complete
   /// computation graph.  To declare a new entity, please see the
-  /// DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN macro in g_factory.h. A
+  /// DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN macro in factory.h. A
   /// command-line interface provided by the entity can be used by a
   /// sot shell to call methods from entities and display the result
   /// of their execution.  Classes that derive from Entity can
diff --git a/include/dynamic-graph/factory.h b/include/dynamic-graph/factory.h
index 44b40c2..c85b16a 100644
--- a/include/dynamic-graph/factory.h
+++ b/include/dynamic-graph/factory.h
@@ -91,8 +91,7 @@ namespace dynamicgraph
   /// appropriate and to check for uniqueness if required.
   ///
   ///
-  /// This class should <b>never</b> be used directly.  Use the
-  /// g_factory global variable instead.  The rationale is that each
+  /// This class is a singleton. The rationale is that each
   /// unique name must identify a unique Entity. The use of a single
   /// instance of this class enforces this behavior, instantiating one
   /// yourself would break this property.
@@ -103,15 +102,14 @@ namespace dynamicgraph
     /// name.
     typedef Entity* (*EntityConstructor_ptr) (const std::string&);
 
-    /// \brief Constructor the factory.
-    ///
-    /// After the initialization, no entities will be available.
-    /// registerEntity has to be used to add new entities to the
-    /// object.
-    explicit FactoryStorage  ();
-
     ~FactoryStorage  ();
 
+    /// \brief Get pointer to unique object of the class
+    static FactoryStorage* getInstance();
+
+    /// \brief Destroy the unique instance of the class
+    static void destroy();
+
     /// \brief Add a new entity to the factory.
     ///
     /// It is not allowed to have several entities using the same
@@ -182,6 +180,14 @@ namespace dynamicgraph
 		      std::ostream& os);
 
   private:
+
+    /// \brief Constructor the factory.
+    ///
+    /// After the initialization, no entities will be available.
+    /// registerEntity has to be used to add new entities to the
+    /// object.
+    explicit FactoryStorage  ();
+
     /// \brief Entity map type.
     ///
     /// This maps entity names to functions pointers which can be
@@ -191,26 +197,11 @@ namespace dynamicgraph
     /// \brief The entity map storing information about how to
     /// instantiate an Entity.
     EntityMap entityMap;
+    
+    /// \pointer to the unique object of the class
+    static FactoryStorage* instance_;
   };
 
-  /// \ingroup dgraph
-  ///
-  /// \brief Global factory.
-  ///
-  /// This global variable is the only valid instance of the
-  /// FactoryStorage class.
-  ///
-  /// This unique instance is to make sure that only only one entity
-  /// list is built.
-  ///
-  /// This global variable must be used to search for entities and
-  /// to instantiate them.
-  ///
-  /// Please use the DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN macro if
-  /// possible to register an entity to this factory.
-  DYNAMIC_GRAPH_DLLAPI extern FactoryStorage g_factory;
-
-
   /// \ingroup dgraph
   ///
   /// \brief This class automatically register an Entity to the
diff --git a/include/dynamic-graph/pool.h b/include/dynamic-graph/pool.h
index 885b171..49536e9 100644
--- a/include/dynamic-graph/pool.h
+++ b/include/dynamic-graph/pool.h
@@ -29,7 +29,7 @@
 namespace dynamicgraph
 {
   /*! @ingroup dgraph
-    \brief This class keep tracks of all the objects in the stack of Tasks.
+    \brief Singleton that keeps track of all the entities.
 
     This class gives access to and remembers all the entities created
     during its life.
@@ -42,11 +42,6 @@ namespace dynamicgraph
     \note From the code it is not very clear why we should not unregister
     from the tasks and the features...
 
-    The role of this class is also to look for the object supporting
-    a command, and to apply this command.
-
-    It also returns signal.
-
   */
   class DYNAMIC_GRAPH_DLLAPI PoolStorage
   {
@@ -57,6 +52,12 @@ namespace dynamicgraph
     /*! \brief Sorted set of entities with unique key (name). */
     typedef std::map< std::string,Entity* > Entities;
 
+    /// \brief Get unique instance of the class.
+    static PoolStorage *getInstance();
+
+    /// \brief Destroy the unique instance of the class
+    static void destroy();
+
     /*! @} */
 
     /*! \brief Default destructor */
@@ -108,7 +109,7 @@ namespace dynamicgraph
       If the method of the object displays some information this will
       be done on os.
 
-      The commands specific to the \b g_pool object are:
+      The commands specific to the \b PoolStorage singleton are:
       \li \b list : List all the entities registered in the pool
     */
     void commandLine (const std::string& objectName,
@@ -128,11 +129,11 @@ namespace dynamicgraph
     */
     /*! \brief Set of basic objects of the SoT */
     Entities entityMap;
-  };
-
-
-  DYNAMIC_GRAPH_DLLAPI extern dynamicgraph::PoolStorage g_pool;
 
+  private:
+    PoolStorage () {}
+    static PoolStorage* instance_;
+  };
 }  // end of namespace dynamicgraph.
 
 #endif //! DYNAMIC_GRAPH_POOL_H
diff --git a/src/dgraph/entity.cpp b/src/dgraph/entity.cpp
index b71ba72..f99bf18 100644
--- a/src/dgraph/entity.cpp
+++ b/src/dgraph/entity.cpp
@@ -42,13 +42,13 @@ entityRegistration  ()
 {
 
   //sotPool.entity[name] = this;
-  g_pool.registerEntity(name,this);
+  PoolStorage::getInstance()->registerEntity(name,this);
 }
 
 void Entity::
 entityDeregistration  ()
 {
-  g_pool.deregisterEntity(name);
+  PoolStorage::getInstance()->deregisterEntity(name);
 }
 
 Entity::
diff --git a/src/dgraph/factory.cpp b/src/dgraph/factory.cpp
index 341c103..77e7e0b 100644
--- a/src/dgraph/factory.cpp
+++ b/src/dgraph/factory.cpp
@@ -24,12 +24,27 @@ using namespace dynamicgraph;
 
 namespace dynamicgraph
 {
+  FactoryStorage* FactoryStorage::getInstance ()
+  {
+    if (instance_ == 0) {
+      instance_ = new FactoryStorage;
+    }
+    return instance_;
+  }
+  
+  void FactoryStorage::destroy()
+  {
+    delete instance_;
+    instance_ = NULL;
+  }
+
   FactoryStorage::FactoryStorage  ()
     : entityMap  ()
   {}
 
   FactoryStorage::~FactoryStorage  ()
   {
+    instance_ = 0;
     dgDEBUGINOUT (25);
   }
 
@@ -43,7 +58,7 @@ namespace dynamicgraph
 	DG_THROW ExceptionFactory
 	  (ExceptionFactory::OBJECT_CONFLICT,
 	   "Another entity class already defined with the same name. ",
-	   "(while adding entity class <%s> inside the g_factory).",
+	   "(while adding entity class <%s> inside the factory).",
 	   entname.c_str  ());
 	dgERRORF ("Another entity class already defined with the same name. "
 		  "(while adding entity class <%s> inside the factory).",
@@ -173,18 +188,18 @@ namespace dynamicgraph
     : entityName (entityClassName)
   {
     dgDEBUGIN (15);
-    g_factory.registerEntity (entityClassName, maker);
+    FactoryStorage::getInstance()->registerEntity (entityClassName, maker);
     dgDEBUGOUT (15);
   }
 
   EntityRegisterer::~EntityRegisterer ()
   {
     dgDEBUGIN(15);
-    g_factory.deregisterEntity (entityName);
+    FactoryStorage::getInstance()->deregisterEntity (entityName);
     dgDEBUGOUT (15);
   }
 
 
   // The global factory.
-  FactoryStorage g_factory;
+  FactoryStorage* FactoryStorage::instance_ = NULL;
 } // end of namespace dynamicgraph.
diff --git a/src/dgraph/pool.cpp b/src/dgraph/pool.cpp
index 30054f4..c2224d3 100644
--- a/src/dgraph/pool.cpp
+++ b/src/dgraph/pool.cpp
@@ -38,6 +38,22 @@ using namespace dynamicgraph;
 /* --- CLASS ----------------------------------------------------------- */
 /* --------------------------------------------------------------------- */
 
+PoolStorage* PoolStorage::
+getInstance()
+{
+  if (instance_ == 0) {
+    instance_ = new PoolStorage;
+  }
+  return instance_;
+}
+
+void PoolStorage::
+destroy()
+{
+  delete instance_;
+  instance_ = NULL;
+}
+
 PoolStorage::
 ~PoolStorage  ()
 {
@@ -52,7 +68,7 @@ PoolStorage::
       deregisterEntity(iter);
       delete (entity);
     }
-
+  instance_ = 0;
   dgDEBUGOUT(15);
 }
 
@@ -301,8 +317,5 @@ getSignal( std::istringstream& sigpath )
   return ent.getSignal( signame );
 }
 
-namespace dynamicgraph {
-	//! The global g_pool object.
-	PoolStorage g_pool;
-}
+PoolStorage* PoolStorage::instance_ = 0;
 
diff --git a/src/traces/tracer.cpp b/src/traces/tracer.cpp
index f85901f..a40c7ad 100644
--- a/src/traces/tracer.cpp
+++ b/src/traces/tracer.cpp
@@ -128,7 +128,7 @@ addSignalToTraceByName( const string& signame,
 {
   dgDEBUGIN(15);
   istringstream iss( signame );
-  SignalBase<int> &sig = g_pool.getSignal(iss);
+  SignalBase<int> &sig = PoolStorage::getInstance()->getSignal(iss);
   addSignalToTrace(sig,filename);
   dgDEBUGOUT(15);
 }
@@ -321,7 +321,7 @@ commandLine( const std::string& cmdLine
     }
   else if( cmdLine=="add" )
     {
-      SignalBase<int> &sig = g_pool.getSignal(cmdArgs);
+      SignalBase<int> &sig = PoolStorage::getInstance()->getSignal(cmdArgs);
       string r; cmdArgs>>ws>>r;
       addSignalToTrace(sig,r);
       dgDEBUG(14)<<"Add <" <<sig.getName ()<<"> with nick \""<<r<<"\""<<endl;
diff --git a/tests/factory.cpp b/tests/factory.cpp
index 716964d..6b79da6 100644
--- a/tests/factory.cpp
+++ b/tests/factory.cpp
@@ -34,17 +34,18 @@ dynamicgraph::Entity* makeEntity(const std::string& objectName)
 
 BOOST_AUTO_TEST_CASE (constructor)
 {
-  dynamicgraph::FactoryStorage factory;
+  dynamicgraph::FactoryStorage::getInstance();
 }
 
 BOOST_AUTO_TEST_CASE (registerEntity)
 {
-  dynamicgraph::FactoryStorage factory;
-  factory.registerEntity ("myEntity", &makeEntity);
+  dynamicgraph::FactoryStorage::getInstance()->registerEntity
+    ("myEntity", &makeEntity);
 
   try
     {
-      factory.registerEntity ("myEntity", &makeEntity);
+      dynamicgraph::FactoryStorage::getInstance()->registerEntity
+	("myEntity", &makeEntity);
       BOOST_ERROR ("Should never happen.");
     }
   catch (const dynamicgraph::ExceptionFactory& exception)
@@ -55,7 +56,8 @@ BOOST_AUTO_TEST_CASE (registerEntity)
 
   try
     {
-      factory.registerEntity ("myEntity", 0);
+      dynamicgraph::FactoryStorage::getInstance()->registerEntity
+	("myEntity", 0);
       BOOST_ERROR ("Should never happen.");
     }
   catch (const dynamicgraph::ExceptionFactory& exception)
@@ -68,13 +70,12 @@ BOOST_AUTO_TEST_CASE (registerEntity)
 
 BOOST_AUTO_TEST_CASE (unregisterEntity)
 {
-  dynamicgraph::FactoryStorage factory;
-  factory.registerEntity ("myEntity", &makeEntity);
-  factory.deregisterEntity ("myEntity");
+  dynamicgraph::FactoryStorage::getInstance()->registerEntity ("myEntity", &makeEntity);
+  dynamicgraph::FactoryStorage::getInstance()->deregisterEntity ("myEntity");
 
   try
     {
-      factory.deregisterEntity ("myEntity");
+      dynamicgraph::FactoryStorage::getInstance()->deregisterEntity("myEntity");
       BOOST_ERROR ("Should never happen.");
     }
   catch (const dynamicgraph::ExceptionFactory& exception)
@@ -85,7 +86,8 @@ BOOST_AUTO_TEST_CASE (unregisterEntity)
 
   try
     {
-      factory.deregisterEntity ("I do not exist.");
+      dynamicgraph::FactoryStorage::getInstance()->deregisterEntity
+	("I do not exist.");
       BOOST_ERROR ("Should never happen.");
     }
   catch (const dynamicgraph::ExceptionFactory& exception)
@@ -97,23 +99,27 @@ BOOST_AUTO_TEST_CASE (unregisterEntity)
 
 BOOST_AUTO_TEST_CASE (newEntity)
 {
-  dynamicgraph::FactoryStorage factory;
-  factory.registerEntity ("myEntity", &makeEntity);
+  dynamicgraph::FactoryStorage::getInstance()->registerEntity
+    ("myEntity", &makeEntity);
 
   {
     boost::shared_ptr<dynamicgraph::Entity> entity
-      (factory.newEntity ("myEntity", "foo"));
+      (dynamicgraph::FactoryStorage::getInstance()->newEntity
+       ("myEntity", "foo"));
 
     boost::shared_ptr<dynamicgraph::Entity> entity2
-      (factory.newEntity ("myEntity", "foo2"));
+      (dynamicgraph::FactoryStorage::getInstance()->newEntity
+       ("myEntity", "foo2"));
 
     boost::shared_ptr<dynamicgraph::Entity> entity3
-      (factory.newEntity ("myEntity", ""));
+      (dynamicgraph::FactoryStorage::getInstance()->newEntity
+       ("myEntity", ""));
   }
 
   try
     {
-      factory.newEntity ("I do not exist.", "");
+      dynamicgraph::FactoryStorage::getInstance()->newEntity
+	("I do not exist.", "");
       BOOST_ERROR ("Should never happen.");
     }
   catch (const dynamicgraph::ExceptionFactory& exception)
@@ -125,10 +131,12 @@ BOOST_AUTO_TEST_CASE (newEntity)
 
 BOOST_AUTO_TEST_CASE (existEntity)
 {
-  dynamicgraph::FactoryStorage factory;
-  factory.registerEntity ("myEntity", &makeEntity);
-
-  BOOST_CHECK (factory.existEntity ("myEntity"));
-  BOOST_CHECK (!factory.existEntity ("myEntity2"));
-  BOOST_CHECK (!factory.existEntity (""));
+  dynamicgraph::FactoryStorage::getInstance()->registerEntity
+    ("myEntity", &makeEntity);
+
+  BOOST_CHECK (dynamicgraph::FactoryStorage::getInstance()->existEntity
+	       ("myEntity"));
+  BOOST_CHECK (!dynamicgraph::FactoryStorage::getInstance()->existEntity
+	       ("myEntity2"));
+  BOOST_CHECK (!dynamicgraph::FactoryStorage::getInstance()->existEntity (""));
 }
diff --git a/tests/pool.cpp b/tests/pool.cpp
index ab323bf..0e8b19d 100644
--- a/tests/pool.cpp
+++ b/tests/pool.cpp
@@ -52,17 +52,21 @@ BOOST_AUTO_TEST_CASE (pool_list)
   MyEntity myEntity("MyEntityInst");
   std::istringstream in;
   output_test_stream output;
-  dynamicgraph::g_pool.commandLine("pool", "list", in, output);
+  dynamicgraph::PoolStorage::getInstance()->commandLine
+    ("pool", "list", in, output);
   BOOST_CHECK (output.is_equal ("MyEntityInst (MyEntity)\n"));
-  dynamicgraph::g_pool.deregisterEntity(myEntity.getName());
+  dynamicgraph::PoolStorage::getInstance()->deregisterEntity
+    (myEntity.getName());
 }
 
 BOOST_AUTO_TEST_CASE (pool_display)
 {
   MyEntity myEntity("MyEntityInst");
   output_test_stream output;
-  dynamicgraph::Entity& e = dynamicgraph::g_pool.getEntity("MyEntityInst");
+  dynamicgraph::Entity& e = dynamicgraph::PoolStorage::getInstance()->getEntity
+    ("MyEntityInst");
   e.display(output);
   BOOST_CHECK (output.is_equal ("Hello! My name is MyEntityInst !\n"));
-  dynamicgraph::g_pool.deregisterEntity(myEntity.getName());
+  dynamicgraph::PoolStorage::getInstance()->deregisterEntity
+    (myEntity.getName());
 }
-- 
GitLab