LCOV - code coverage report
Current view: top level - atermpp/include/mcrl2/atermpp/detail - thread_aterm_pool.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 19 20 95.0 %
Date: 2024-05-04 03:44:52 Functions: 5 6 83.3 %
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             : #ifndef ATERMPP_DETAIL_THREAD_ATERM_POOL_H
      11             : #define ATERMPP_DETAIL_THREAD_ATERM_POOL_H
      12             : 
      13             : #include "mcrl2/atermpp/detail/aterm_pool.h"
      14             : #include "mcrl2/atermpp/detail/aterm_container.h"
      15             : #include "mcrl2/utilities/hashtable.h"
      16             : #include "mcrl2/utilities/shared_mutex.h"
      17             : 
      18             : #include <atomic>
      19             : 
      20             : namespace atermpp
      21             : {
      22             : namespace detail
      23             : {
      24             : 
      25             : /// \brief This is a thread's specific access to the global aterm pool which ensures that
      26             : ///        garbage collection and hash table resizing can proceed.
      27             : class thread_aterm_pool final : public mcrl2::utilities::noncopyable
      28             : {
      29             : public:
      30         144 :   thread_aterm_pool(aterm_pool& global_pool)
      31         144 :     : m_pool(global_pool),
      32         144 :       m_shared_mutex(global_pool.shared_mutex()),
      33         144 :       m_variables(new mcrl2::utilities::hashtable<aterm*>()),
      34         144 :       m_containers(new mcrl2::utilities::hashtable<detail::aterm_container*>()),
      35         144 :       m_thread_interface(global_pool, std::bind(&thread_aterm_pool::mark, this), std::bind(&thread_aterm_pool::print_local_performance_statistics, this), std::bind(&thread_aterm_pool::protection_set_size, this))
      36             :   {
      37             :     /// Identify the first constructor call as the main thread.
      38             :     static bool is_main_thread = true;
      39         144 :     if (is_main_thread)
      40             :     {
      41         143 :       m_is_main_thread = true;
      42         143 :       is_main_thread = false;
      43             :     }
      44         144 :   }
      45             : 
      46         144 :   ~thread_aterm_pool() 
      47             :   {
      48             :       // We leak values for the global aterm pool since they contain global variables (for which initialisation order is undefined).
      49         144 :     if (!m_is_main_thread)
      50             :     {
      51             :       // We need to prematurely unregister this thread pool since we are going to delete reference variables.
      52           1 :       m_thread_interface.unregister();
      53           1 :       delete m_variables;
      54           1 :       delete m_containers;
      55             :     }
      56         144 :   }
      57             : 
      58             :   /// \details threadsafe
      59             :   inline function_symbol create_function_symbol(const std::string& name, const std::size_t arity, const bool check_for_registered_functions = false);
      60             : 
      61             :   /// \details threadsafe
      62             :   inline function_symbol create_function_symbol(std::string&& name, const std::size_t arity, const bool check_for_registered_functions = false);
      63             : 
      64             :   /// \details threadsafe
      65             :   inline void create_int(aterm& term, std::size_t val);
      66             : 
      67             :   /// \details threadsafe
      68             :   inline void create_term(aterm& term, const function_symbol& sym);
      69             : 
      70             :   /// \details threadsafe
      71             :   template<class ...Terms>
      72             :   inline void create_appl(aterm& term, const function_symbol& sym, const Terms&... arguments);
      73             : 
      74             :   /// \details threadsafe
      75             :   template<class Term, class INDEX_TYPE, class ...Terms>
      76             :   inline void create_appl_index(aterm& term, const function_symbol& sym, const Terms&... arguments);
      77             : 
      78             :   /// \details threadsafe
      79             :   template<typename ForwardIterator>
      80             :   inline void create_appl_dynamic(aterm& term,
      81             :       const function_symbol& sym,
      82             :       ForwardIterator begin,
      83             :       ForwardIterator end);
      84             : 
      85             :   /// \threadsafe
      86             :   template<typename InputIterator, typename ATermConverter>
      87             :   inline void create_appl_dynamic(aterm& term,
      88             :       const function_symbol& sym,
      89             :       ATermConverter convert_to_aterm,
      90             :       InputIterator begin,
      91             :       InputIterator end);
      92             : 
      93             :   /// \brief Consider the given variable when marking underlying terms.
      94             :   inline void register_variable(aterm* variable);
      95             : 
      96             :   /// \brief Removes the given variable from the active variables.
      97             :   inline void deregister_variable(aterm* variable);
      98             : 
      99             :   /// \brief Consider the given container when marking underlying terms.
     100             :   inline void register_container(aterm_container* variable);
     101             : 
     102             :   /// \brief Removes the given container from the active variables.
     103             :   inline void deregister_container(aterm_container* variable);
     104             : 
     105             :   // Implementation of thread_aterm_pool_interface
     106             :   inline void mark();
     107             :   inline void print_local_performance_statistics() const;
     108             :   inline std::size_t protection_set_size() const;
     109             : 
     110             :   /// Acquire a shared lock on this thread aterm pool.
     111   190108996 :   inline mcrl2::utilities::shared_guard lock_shared() { return m_shared_mutex.lock_shared(); }
     112             : 
     113             :   /// Acquire an exclusive lock
     114        4030 :   inline mcrl2::utilities::lock_guard lock() { return m_shared_mutex.lock(); }
     115             : 
     116             :   /// Returns true iff we are in a shared section.
     117           0 :   inline bool is_shared_locked() { return m_shared_mutex.is_shared_locked(); }
     118             : 
     119             :   /// Triggers a global garbage collection
     120        1002 :   inline void collect() { m_pool.collect(m_shared_mutex); }
     121             : 
     122             : private:
     123             :   aterm_pool& m_pool;
     124             : 
     125             :   /// Keeps track of pointers to all existing aterm variables and containers.
     126             :   mcrl2::utilities::shared_mutex m_shared_mutex;
     127             :   mcrl2::utilities::hashtable<aterm*>* m_variables;
     128             :   mcrl2::utilities::hashtable<detail::aterm_container*>* m_containers;
     129             : 
     130             :   std::size_t m_variable_insertions = 0;
     131             :   std::size_t m_container_insertions = 0;
     132             :   std::stack<std::reference_wrapper<_aterm>> m_todo; ///< A reusable todo stack.
     133             : 
     134             :   bool m_is_main_thread = false;
     135             : 
     136             :   /// The registered thread aterm pool.
     137             :   thread_aterm_pool_interface m_thread_interface; 
     138             : };
     139             : 
     140             : /// \brief A reference to the thread local term pool storage
     141             : thread_aterm_pool& g_thread_term_pool();
     142             : 
     143             : } // namespace detail
     144             : } // namespace atermpp
     145             : 
     146             : #include "thread_aterm_pool_implementation.h"
     147             : 
     148             : #endif // ATERMPP_DETAIL_ATERM_POOL_H

Generated by: LCOV version 1.14