LCOV - code coverage report
Current view: top level - atermpp/source - function_symbol_pool.cpp (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 52 56 92.9 %
Date: 2020-07-04 00:44:36 Functions: 9 10 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Maurice Laveaux
       2             : // Copyright: see the accompanying file COPYING or copy at
       3             : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
       4             : //
       5             : // Distributed under the Boost Software License, Version 1.0.
       6             : // (See accompanying file LICENSE_1_0.txt or copy at
       7             : // http://www.boost.org/LICENSE_1_0.txt)
       8             : //
       9             : 
      10             : #include "mcrl2/atermpp/detail/function_symbol_pool.h"
      11             : 
      12             : #include "mcrl2/utilities/unused.h"
      13             : 
      14             : using namespace atermpp;
      15             : using namespace atermpp::detail;
      16             : using namespace mcrl2::utilities;
      17             : 
      18         141 : function_symbol_pool::function_symbol_pool()
      19             : {
      20             :   // Initialize the default function symbols.
      21         141 :   m_as_int = create("<aterm_int>", 0);
      22         141 :   m_as_list = create("<list_constructor>", 2);
      23         141 :   m_as_empty_list = create("<empty_list>", 0);
      24             : 
      25             :   // Initialize the global copies of these default function symbols.
      26         141 :   g_as_int = m_as_int;
      27         141 :   g_as_list = m_as_list;
      28         141 :   g_as_empty_list = m_as_empty_list;
      29         141 : }
      30             : 
      31           0 : function_symbol_pool::~function_symbol_pool()
      32             : {
      33           0 :   print_performance_stats();
      34           0 : }
      35             : 
      36     1360663 : function_symbol function_symbol_pool::create(const std::string& name, const std::size_t arity, const bool check_for_registered_functions)
      37             : {
      38     1360663 :   auto it = m_symbol_set.find(name, arity);
      39     1360663 :   if (it != m_symbol_set.end())
      40             :   {
      41             :     if (EnableFunctionSymbolMetrics) { m_function_symbol_metrics.hit(); }
      42             : 
      43             :     // The element already exists so return it.
      44     1317885 :     return function_symbol(_function_symbol::ref(&(*it)));
      45             :   }
      46             :   else
      47             :   {
      48             :     if (EnableFunctionSymbolMetrics) { m_function_symbol_metrics.miss(); }
      49             : 
      50       42778 :     const _function_symbol& symbol = *m_symbol_set.emplace(name, arity).first;
      51       42778 :     if (check_for_registered_functions)
      52             :     {
      53             :       // Check whether there is a registered prefix p such that name equal pn where n is a number.
      54             :       // In that case prevent that pn will be generated as a fresh function name.
      55       38196 :       std::size_t start_of_index = name.find_last_not_of("0123456789") + 1;
      56             : 
      57       38196 :       if (start_of_index < name.size()) // Otherwise there is no trailing number.
      58             :       {
      59        8708 :         std::string potential_number = name.substr(start_of_index); // Get the trailing string after prefix_ of function_name.
      60        8708 :         std::string prefix = name.substr(0, start_of_index);
      61        4354 :         auto prefix_it = m_prefix_to_register_function_map.find(prefix);
      62        4354 :         if (prefix_it != m_prefix_to_register_function_map.end())  // points to the prefix.
      63             :         {
      64             :           try
      65             :           {
      66           1 :             std::size_t number = std::stoul(potential_number);
      67           1 :             *prefix_it->second = std::max(*prefix_it->second, number + 1); // Set the index belonging to the found prefix to at least a safe number+1.
      68             :           }
      69           0 :           catch (std::exception&)
      70             :           {
      71             :             // Can be std::invalid_argument or an out_of_range exception.
      72             :             // In both cases nothing needs to be done, and the exception can be ignored.
      73             :           }
      74             :         }
      75             :       }
      76             :     }
      77             : 
      78       42778 :     return function_symbol(_function_symbol::ref(&symbol));
      79             :   }
      80             : }
      81             : 
      82         687 : void function_symbol_pool::destroy(const _function_symbol& f)
      83             : {
      84         687 :   assert(f.reference_count() == 0);
      85             : 
      86             :   // Remove it from the function symbol pool.
      87         687 :   m_symbol_set.erase(f);
      88         687 : }
      89             : 
      90        2657 : void function_symbol_pool::deregister(const std::string& prefix)
      91             : {
      92        2657 :   m_prefix_to_register_function_map.erase(prefix);
      93        2657 : }
      94             : 
      95        2657 : std::shared_ptr<std::size_t> function_symbol_pool::register_prefix(const std::string& prefix)
      96             : {
      97        2657 :   auto it = m_prefix_to_register_function_map.find(prefix);
      98        2657 :   if (it != m_prefix_to_register_function_map.end())
      99             :   {
     100         740 :     return it->second;
     101             :   }
     102             :   else
     103             :   {
     104        1917 :     std::size_t index = get_sufficiently_large_postfix_index(prefix);
     105        3834 :     std::shared_ptr<std::size_t> shared_index = std::make_shared<std::size_t>(index);
     106        1917 :     m_prefix_to_register_function_map[prefix] = shared_index;
     107        1917 :     return shared_index;
     108             :   }
     109             : }
     110             : 
     111        1917 : std::size_t function_symbol_pool::get_sufficiently_large_postfix_index(const std::string& prefix) const
     112             : {
     113        1917 :   std::size_t index = 0;
     114      837740 :   for (const auto& f : m_symbol_set)
     115             :   {
     116      835823 :     const std::string& function_name = f.name();
     117             : 
     118      835823 :     if (function_name.compare(0, prefix.size(), prefix) == 0)   // The function name starts with the prefix
     119             :     {
     120      177398 :       std::string potential_number = function_name.substr(prefix.size()); // Get the trailing string after prefix_ of function_name.
     121             :       std::size_t end_of_number;
     122             :       try
     123             :       {
     124       88699 :         std::size_t number = std::stoul(potential_number, &end_of_number);
     125       86654 :         if (end_of_number == potential_number.size()) // A proper number was read.
     126             :         {
     127       86654 :           if (number >= index)
     128             :           {
     129        2808 :             index = number + 1;
     130             :           }
     131             :         }
     132             :       }
     133        2045 :       catch (std::exception&)
     134             :       {
     135             :         // Can be std::invalid_argument or an out_of_range exception.
     136             :         // In both cases nothing needs to be done, and the exception can be ignored.
     137             :       }
     138             :     }
     139             :   }
     140             : 
     141        1917 :   return index;
     142             : }
     143             : 
     144           2 : void function_symbol_pool::print_performance_stats() const noexcept
     145             : {
     146             :   if (EnableFunctionSymbolHashtableMetrics)
     147             :   {
     148             :     print_performance_statistics(m_symbol_set);
     149             :   }
     150             : 
     151             :   if (EnableFunctionSymbolMetrics)
     152             :   {
     153             :     mCRL2log(mcrl2::log::info, "Performance") << "g_function_symbol_pool: Stores " << size() << " function symbols. create() " << m_function_symbol_metrics.message() << ".\n";
     154             :   }
     155             : 
     156             :   if (EnableReferenceCountMetrics)
     157             :   {
     158             :     mCRL2log(mcrl2::log::info, "Performance") << "g_function_symbol_pool: all reference counts changed " << _function_symbol::reference_count_changes() << " times.\n";
     159             :   }
     160         425 : }

Generated by: LCOV version 1.13