LCOV - code coverage report
Current view: top level - include/parallel - threads.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 2 2 100.0 %
Date: 2025-08-19 19:27:09 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : #ifndef LIBMESH_THREADS_H
      20             : #define LIBMESH_THREADS_H
      21             : 
      22             : // Local includes
      23             : #include "libmesh/libmesh_config.h"
      24             : #include "libmesh/libmesh_common.h"  // for libmesh_assert
      25             : 
      26             : 
      27             : // Compile-time check: TBB and pthreads are now mutually exclusive.
      28             : #if defined(LIBMESH_HAVE_TBB_API) && defined(LIBMESH_HAVE_PTHREAD)
      29             : MULTIPLE THREADING MODELS CANNOT BE SIMULTANEOUSLY ACTIVE
      30             : #endif
      31             : 
      32             : namespace libMesh
      33             : {
      34             : 
      35             : /**
      36             :  * The Threads namespace is for wrapper functions
      37             :  * for common general multithreading algorithms and tasks.
      38             :  */
      39             : namespace Threads
      40             : {
      41             : 
      42             : /**
      43             :  * A boolean which is true iff we are in a Threads:: function
      44             :  * It may be useful to assert(!Threads::in_threads) in any code
      45             :  * which is known to not be thread-safe.
      46             :  */
      47             : extern bool in_threads;
      48             : 
      49             : /**
      50             :  * We use a class to turn Threads::in_threads on and off, to be
      51             :  * exception-safe.
      52             :  */
      53             : class BoolAcquire
      54             : {
      55             : public:
      56             :   explicit
      57     4245695 :   BoolAcquire(bool & b) : _b(b) { libmesh_assert(!_b); _b = true; }
      58             : 
      59     4245695 :   ~BoolAcquire() { libmesh_exceptionless_assert(_b); _b = false; }
      60             : private:
      61             :   bool & _b;
      62             : };
      63             : 
      64             : /**
      65             :  * We use a class to turn perf logging off and on within threads, to
      66             :  * be exception-safe and to avoid forcing indirect inclusion of
      67             :  * libmesh_logging.h everywhere.
      68             :  *
      69             :  * If we have logging disabled, constructing this class should do
      70             :  * nothing; [[maybe_unused]] disables warnings about that.
      71             :  */
      72             : class [[maybe_unused]] DisablePerfLogInScope
      73             : {
      74             : public:
      75             : #ifndef LIBMESH_ENABLE_PERFORMANCE_LOGGING
      76             :   DisablePerfLogInScope() = default;
      77             :   ~DisablePerfLogInScope() = default;
      78             : #else
      79             :   DisablePerfLogInScope();
      80             :   ~DisablePerfLogInScope();
      81             : private:
      82             :   const bool _logging_was_enabled;
      83             : #endif
      84             : };
      85             : 
      86             : 
      87             : /**
      88             :  * Simple compatibility class for std::thread 'concurrent' execution.
      89             :  * Not at all concurrent, but provides a compatible interface.
      90             :  */
      91             : class NonConcurrentThread
      92             : {
      93             : public:
      94             :   /**
      95             :    * Constructor.  Takes a callable function object and executes it.
      96             :    * Our wrapper class actually blocks execution until the thread
      97             :    * is complete.
      98             :    */
      99             :   template <typename Callable>
     100             :   NonConcurrentThread (Callable f) { f(); }
     101             : 
     102             :   /**
     103             :    * Join is a no-op, since the constructor blocked until completion.
     104             :    */
     105             :   void join() {}
     106             : 
     107             :   /**
     108             :    * Always joinable.
     109             :    */
     110             :   bool joinable() const { return true; }
     111             : };
     112             : 
     113             : } // namespace Threads
     114             : 
     115             : } // namespace libMesh
     116             : 
     117             : 
     118             : 
     119             : // Include thread-model specific algorithms and objects.  These
     120             : // headers include headers of their own and handle their own
     121             : // namespacing.
     122             : #define LIBMESH_SQUASH_HEADER_WARNING
     123             : #ifdef LIBMESH_HAVE_TBB_API
     124             : # include "libmesh/threads_tbb.h"
     125             : #elif LIBMESH_HAVE_PTHREAD
     126             : # include "libmesh/threads_pthread.h"
     127             : #else
     128             : # include "libmesh/threads_none.h"
     129             : #endif
     130             : 
     131             : 
     132             : 
     133             : namespace libMesh
     134             : {
     135             : 
     136             : namespace Threads
     137             : {
     138             : 
     139             : /**
     140             :  * Blocked range which can be subdivided and executed in parallel.
     141             :  */
     142             : template <typename T>
     143             : class BlockedRange
     144             : {
     145             : public:
     146             :   /**
     147             :    * Allows an \p StoredRange to behave like an STL container.
     148             :    */
     149             :   typedef T const_iterator;
     150             : 
     151             :   /**
     152             :    * Constructor. Optionally takes the \p grainsize parameter, which is the
     153             :    * smallest chunk the range may be broken into for parallel
     154             :    * execution.
     155             :    */
     156             :   explicit BlockedRange (const unsigned int new_grainsize = 1000) :
     157             :     _grainsize(new_grainsize)
     158             :   {}
     159             : 
     160             :   /**
     161             :    * Constructor.  Takes the beginning and end of the range.
     162             :    * Optionally takes the \p grainsize parameter, which is the
     163             :    * smallest chunk the range may be broken into for parallel
     164             :    * execution.
     165             :    */
     166             :   BlockedRange (const const_iterator first,
     167             :                 const const_iterator last,
     168             :                 const unsigned int new_grainsize = 1000) :
     169             :     _grainsize(new_grainsize)
     170             :   {
     171             :     this->reset(first, last);
     172             :   }
     173             : 
     174             :   /**
     175             :    * Copy constructor.  The \p StoredRange can be copied into
     176             :    * subranges for parallel execution.  In this way the
     177             :    * initial \p StoredRange can be thought of as the root of
     178             :    * a binary tree.  The root element is the only element
     179             :    * which interacts with the user.  It takes a specified
     180             :    * range of objects and packs it into a contiguous vector
     181             :    * which can be split efficiently. However, there is no need
     182             :    * for the child ranges to contain this vector, so long as
     183             :    * the parent outlives the children.  So we implement
     184             :    * the copy constructor to specifically omit the \p _objs
     185             :    * vector.
     186             :    */
     187             :   BlockedRange (const BlockedRange<T> & r):
     188             :     _end(r._end),
     189             :     _begin(r._begin),
     190             :     _grainsize(r._grainsize)
     191             :   {}
     192             : 
     193             :   /**
     194             :    * Splits the range \p r.  The first half
     195             :    * of the range is left in place, the second
     196             :    * half of the range is placed in *this.
     197             :    */
     198             :   BlockedRange (BlockedRange<T> & r, Threads::split ) :
     199             :     _end(r._end),
     200             :     _begin(r._begin),
     201             :     _grainsize(r._grainsize)
     202             :   {
     203             :     const_iterator
     204             :       beginning = r._begin,
     205             :       ending    = r._end,
     206             :       middle    = beginning + (ending - beginning)/2u;
     207             : 
     208             :     r._end = _begin = middle;
     209             :   }
     210             : 
     211             :   /**
     212             :    * Resets the \p StoredRange to contain [first,last).
     213             :    */
     214             :   void reset (const const_iterator first,
     215             :               const const_iterator last)
     216             :   {
     217             :     _begin = first;
     218             :     _end   = last;
     219             :   }
     220             : 
     221             :   /**
     222             :    * Beginning of the range.
     223             :    */
     224             :   const_iterator begin () const { return _begin; }
     225             : 
     226             :   /**
     227             :    * End of the range.
     228             :    */
     229             :   const_iterator end () const { return _end; }
     230             : 
     231             :   /**
     232             :    * The grain size for the range.  The range will be subdivided into
     233             :    * subranges not to exceed the grain size.
     234             :    */
     235             :   unsigned int grainsize () const {return _grainsize;}
     236             : 
     237             :   /**
     238             :    * Set the grain size.
     239             :    */
     240             :   void grainsize (const unsigned int & gs) {_grainsize = gs;}
     241             : 
     242             :   /**
     243             :    * \returns The size of the range.
     244             :    */
     245             :   int size () const { return (_end -_begin); }
     246             : 
     247             :   //------------------------------------------------------------------------
     248             :   // Methods that implement Range concept
     249             :   //------------------------------------------------------------------------
     250             : 
     251             :   /**
     252             :    * \returns \p true if the range is empty.
     253             :    */
     254             :   bool empty() const { return (_begin == _end); }
     255             : 
     256             :   /**
     257             :    * \returns \p true if the range can be subdivided.
     258             :    */
     259             :   bool is_divisible() const { return ((_begin + this->grainsize()) < _end); }
     260             : 
     261             : private:
     262             : 
     263             :   const_iterator _end;
     264             :   const_iterator _begin;
     265             :   unsigned int _grainsize;
     266             : };
     267             : 
     268             : 
     269             : 
     270             : /**
     271             :  * A convenient spin mutex object which can be used for obtaining locks.
     272             :  */
     273             : extern spin_mutex spin_mtx;
     274             : 
     275             : /**
     276             :  * A convenient recursive mutex object which can be used for obtaining locks.
     277             :  */
     278             : extern recursive_mutex recursive_mtx;
     279             : 
     280             : } // namespace Threads
     281             : 
     282             : } // namespace libMesh
     283             : 
     284             : #endif // LIBMESH_THREADS_H

Generated by: LCOV version 1.14