Program Listing for File OpenMPExecutor.h

↰ Return to documentation for file (ADS/parallel/OpenMPExecutor.h)

/*--------------------------------------------------------------------------*/
/*------------------------- File OpenMPExecutor.h --------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*----------------------------- DEFINITIONS --------------------------------*/
/*--------------------------------------------------------------------------*/

#ifndef __ADS_OpenMPExecutor
 #define __ADS_OpenMPExecutor
                      /* self-identification: #endif constant */

#if defined( _OPENMP )

/*--------------------------------------------------------------------------*/
/*------------------------------ INCLUDES ----------------------------------*/
/*--------------------------------------------------------------------------*/

#include "ADS/Contract.h"
#include "ADS/parallel/Executor.h"

#include <omp.h>

#include <algorithm>
#include <cstddef>

/*--------------------------------------------------------------------------*/
/*--------------------------- NAMESPACE ------------------------------------*/
/*--------------------------------------------------------------------------*/

namespace ADS {

/*--------------------------------------------------------------------------*/
/*-------------------------- CLASS OpenMPExecutor --------------------------*/
/*--------------------------------------------------------------------------*/

class OpenMPExecutor {

/*--------------------------------------------------------------------------*/
 public:

 explicit OpenMPExecutor( std::size_t p = 0 )
  : f_p( p ? p : std::size_t( omp_get_max_threads() ) ) {
  ADS_PRE( f_p >= 1 );
  }

 [[nodiscard]] std::size_t concurrency( void ) const { return( f_p ); }

 template< class F >
 void bulk( std::size_t n , F && f ) {
  if( ( n <= 1 ) || ( f_p == 1 ) ) {
   for( std::size_t i = 0 ; i < n ; ++i )
    f( i );
   return;
   }
  detail::FirstError error;
  const long m = long( n );
  #pragma omp parallel for schedule( dynamic , 1 ) \
                           num_threads( int( std::min( f_p , n ) ) )
  for( long i = 0 ; i < m ; ++i ) {
   if( error.failed() )
    continue;
   try {
    f( std::size_t( i ) );
    }
   catch( ... ) {
    error.keep();
    }
   }
  error.rethrow();
  }

 template< class F , class G >
 void invoke( F && f , G && g ) {
  bulk( 2 , [ & ]( std::size_t i ) { if( i == 0 ) f(); else g(); } );
  }

/*--------------------------------------------------------------------------*/
 private:

 std::size_t f_p;
 };  // end( class OpenMPExecutor )

/*--------------------------------------------------------------------------*/

}  // end( namespace ADS )

#endif  /* _OPENMP */

/*--------------------------------------------------------------------------*/

#endif  /* OpenMPExecutor.h included */

/*--------------------------------------------------------------------------*/
/*----------------------- End File OpenMPExecutor.h ------------------------*/
/*--------------------------------------------------------------------------*/