From 44ff9b6279705bc8948bfd3cf43230c915c9b9b0 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Tue, 27 Oct 2015 18:11:48 +0100
Subject: [PATCH] NGeni -> SGeniRegistry, to ensure clean tear-down.

---
 TODO                  |  2 ++
 pub/lib/commands.cpp  |  2 +-
 pub/lib/fregistry.hpp |  2 +-
 pub/lib/func.hpp      |  1 +
 pub/lib/geni.cpp      | 19 ++++++-------------
 pub/lib/geni.hpp      | 14 ++++++++------
 pub/lib/registry.hpp  | 38 +++++++++++++++++++++++++++++++++++---
 pub/lib/toplevel.cpp  |  5 ++++-
 pub/lib/xax_lex.lpp   |  3 ++-
 9 files changed, 60 insertions(+), 26 deletions(-)

diff --git a/TODO b/TODO
index 9fb20cc7..ef621e21 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,7 @@
 == Todo at once ==
 
+refactor func+op registration so that registered object can be const
+
 or+: value does not arrive!
 
 cp: table header placement, correct 1-R^2
diff --git a/pub/lib/commands.cpp b/pub/lib/commands.cpp
index 0e564eaa..8e05a12d 100644
--- a/pub/lib/commands.cpp
+++ b/pub/lib/commands.cpp
@@ -103,7 +103,7 @@ bool frida_command( string cmd )
             "  hic  dimension-reducing functionals of curves\n"
             ;
     } else if (cmd == "hid" || cmd == "oio") {
-        NGeni::display_genis();
+        SGeniRegistry::get_instance()->display_genis();
     } else if (cmd == "hic") {
         NCvin::display_cvins();
     } else if (cmd == "ho") {
diff --git a/pub/lib/fregistry.hpp b/pub/lib/fregistry.hpp
index f352f976..21be3258 100644
--- a/pub/lib/fregistry.hpp
+++ b/pub/lib/fregistry.hpp
@@ -47,7 +47,7 @@ typedef void   (*func_e_eee) (double&,double&, double,double, double,double, dou
 
 //! A singleton class, holding a collection of CFunc's.
 
-class SFuncRegistry : public IRegistry<CFunc>, public ISingleton<SFuncRegistry> {
+class SFuncRegistry : public IRegistryTmp<CFunc>, public ISingleton<SFuncRegistry> {
  private:
     virtual string type_name() const { return "operator and function"; }
     void register_fct_template(
diff --git a/pub/lib/func.hpp b/pub/lib/func.hpp
index c10252d3..e56d2953 100644
--- a/pub/lib/func.hpp
+++ b/pub/lib/func.hpp
@@ -43,6 +43,7 @@ class CFuncMetadata {
 class CFunc : public CFuncMetadata {
  public:
     CFunc( const CFuncMetadata& _m ) : CFuncMetadata( _m ) {}
+    ~CFunc() { for( auto t: tyfuList ) delete t; }
     vector<const CTypedFunc*> tyfuList; //! List of available typed function instances.
     const CTypedFunc* find_exact_tyfu( string intypes ) const;
     const CTypedFunc* find_tyfu( string intypes, bool want_error ) const;
diff --git a/pub/lib/geni.cpp b/pub/lib/geni.cpp
index 1146584f..fb982b50 100644
--- a/pub/lib/geni.cpp
+++ b/pub/lib/geni.cpp
@@ -268,19 +268,12 @@ CGeni::CGeni( string _name, int _narg, string _default_arg_str, geni_eval _eval,
         default_arg[iarg] = user_xaxparse( default_expr[iarg].c_str() );
 }
 
-const CGeni* NGeni::find( string key )
-{
-    auto pos = gmap.find(key);
-    return pos == gmap.end() ? nullptr : pos->second;
-}
-
 void CGeni::register_me() const
 {
-    NGeni::gmap.insert( make_pair( name, this ) );
-    NGeni::glist.push_back( this );
+    SGeniRegistry::get_instance()->push_back( name, this );
 }
 
-void NGeni::display_genis()
+void SGeniRegistry::display_genis() const
 {
     cout << "Dimension-reducing functionals of data sets.\n";
     cout << "Usage:\n";
@@ -293,13 +286,13 @@ void NGeni::display_genis()
     cout << "  - list shows default arguments that are assumed when functional name is not\n";
     cout << "      followed by a parenthesis: 'integral' is shorthand for 'integral(x,y)'\n";
     cout << "Implemented functionals:\n";
-    for( auto g = glist.begin(); g!=glist.end(); ++g ) {
-        string s1 = (*g)->name + "(" + (*g)->default_arg_str + ")";
-        cout << "  " << str( format("%-14s") % s1 ) << (*g)->com << "\n";
+    for( const CGeni* g: FList ) {
+        string s1 = g->name + "(" + g->default_arg_str + ")";
+        cout << "  " << str( format("%-14s") % s1 ) << g->com << "\n";
     }
 }
 
-void NGeni::initialize()
+void SGeniRegistry::initialize()
 {
     // operators by precedence (as in xax_yacc.ypp):
     (new CGeni( "valmin", 1, "y", geni_valmin, "a",
diff --git a/pub/lib/geni.hpp b/pub/lib/geni.hpp
index dc803146..050f510e 100644
--- a/pub/lib/geni.hpp
+++ b/pub/lib/geni.hpp
@@ -7,6 +7,7 @@
 //! \file  geni.hpp
 //! \brief Collection NGeni of generalized integral wrappers CGeni.
 
+#include "registry.hpp"
 
 //!  Function type: Evaluate generalized integral for given vector(s).
 
@@ -32,10 +33,11 @@ class CGeni {
 };
 
 
-//! Collection of function wrappers CFunc
+class SGeniRegistry : public IRegistry<CGeni>, public ISingleton<SGeniRegistry> {
+ private:
+    virtual string type_name() const { return "generalized integrals"; }
+ public:
+    void display_genis() const;
+    static void initialize();
+};
 
-namespace NGeni { // public (short) interface
-    void initialize();
-    const CGeni* find( string nam );
-    void display_genis();
-}
diff --git a/pub/lib/registry.hpp b/pub/lib/registry.hpp
index bf63ead3..6e53d969 100644
--- a/pub/lib/registry.hpp
+++ b/pub/lib/registry.hpp
@@ -13,20 +13,52 @@
 #include "defs.hpp"
 #include "singleton.hpp"
 
+//! Mixin interface for registries holding objects of type T; temporary version for SFuncRegistry.
+
+template<class T>
+class IRegistryTmp {
+ protected:
+    virtual string type_name() const = 0;
+    map<string, /*const*/T*> FMap;       //! unsorted hash, for expression evaluation
+    vector<const T*> FList;    //! sorted array, for help text
+ public:
+    virtual ~IRegistryTmp() { for ( const T* F: FList ) delete F; }
+    void push_back( const string& key, const T* val ){
+        if ( FMap.find(key) != FMap.end() )
+            throw "Duplicate registry entry " + key;
+        FMap.insert( std::make_pair( key, val ) );
+        FList.push_back( val );
+    }
+    const T* find( const string& key ) const {
+        auto pos = FMap.find(key);
+        return pos == FMap.end() ? nullptr : pos->second; }
+    const T* find_or_fail( const string& key ) const {
+        const T* ret = find( key );
+        if( !ret )
+            throw "Cannot find '" + key + "' in " + type_name() + " registry";
+        return ret; }
+};
+
 //! Mixin interface for registries holding objects of type T
 
 template<class T>
 class IRegistry {
  protected:
     virtual string type_name() const = 0;
-    map<string,T*> FMap;       //! unsorted hash, for expression evaluation
+    map<string, const T*> FMap;       //! unsorted hash, for expression evaluation
     vector<const T*> FList;    //! sorted array, for help text
  public:
     virtual ~IRegistry() { for ( const T* F: FList ) delete F; }
-    const T* find( string key ) const {
+    void push_back( const string& key, const T* val ){
+        if ( FMap.find(key) != FMap.end() )
+            throw "Duplicate registry entry " + key;
+        FMap.insert( std::make_pair( key, val ) );
+        FList.push_back( val );
+    }
+    const T* find( const string& key ) const {
         auto pos = FMap.find(key);
         return pos == FMap.end() ? nullptr : pos->second; }
-    const T* find_or_fail( string key ) const {
+    const T* find_or_fail( const string& key ) const {
         const T* ret = find( key );
         if( !ret )
             throw "Cannot find '" + key + "' in " + type_name() + " registry";
diff --git a/pub/lib/toplevel.cpp b/pub/lib/toplevel.cpp
index f8b4a94a..6b575542 100644
--- a/pub/lib/toplevel.cpp
+++ b/pub/lib/toplevel.cpp
@@ -41,6 +41,8 @@ void fstring_initialize(); // implemented in fstring.cpp; no .hpp file
 
 // Initializiations.
 auto GFuncRegistry = SFuncRegistry::get_instance(); // global for use in xax_lex and xax_yacc
+auto GGeniRegistry = SGeniRegistry::get_instance(); // global for use in xax_lex and xax_yacc
+
 SRegistry* GReg = &(SRegistry::getInstance());
 
 
@@ -63,6 +65,7 @@ void my_gsl_error_handler ( const char * reason, const char * file, int line, in
 void atexit_handler()
 {
     SFuncRegistry::reset_instance();
+    SGeniRegistry::reset_instance();
 }
 
 
@@ -141,7 +144,7 @@ CFrida::CFrida()
     fbase_initialize();
     fassign_initialize();
     fstring_initialize();
-    NGeni::initialize();
+    SGeniRegistry::initialize();
     NCvin::initialize();
 
     if( std::atexit( atexit_handler ) ) {
diff --git a/pub/lib/xax_lex.lpp b/pub/lib/xax_lex.lpp
index 37044b0c..e17e007e 100644
--- a/pub/lib/xax_lex.lpp
+++ b/pub/lib/xax_lex.lpp
@@ -59,6 +59,7 @@ RNode node_PI( new CNodeVal( M_PI ) );
 RNode node_INF( new CNodeVal( INFINITY ) );
 
 extern SFuncRegistry* GFuncRegistry;
+extern SGeniRegistry* GGeniRegistry;
 %}
 
 DIG      [0-9]
@@ -156,7 +157,7 @@ e {	xaxlval->t = node_E;
             xaxlval->p = (void*) f1;
             return FNCT;
         }
-	if ( const CGeni* g1 = NGeni::find(xaxtext) ) {
+	if ( const CGeni* g1 = GGeniRegistry->find(xaxtext) ) {
             xaxlval->p = (void*) g1;
             return GENI;
 	}
-- 
GitLab