OpenMC/include/openmc/openmp_interface.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

111 lines
2.5 KiB
C
Raw Permalink Normal View History

#ifndef OPENMC_OPENMP_INTERFACE_H
#define OPENMC_OPENMP_INTERFACE_H
#ifdef _OPENMP
#include <omp.h>
#endif
namespace openmc {
//==============================================================================
//! Accessor functions related to number of threads and thread number
//==============================================================================
inline int num_threads()
{
#ifdef _OPENMP
return omp_get_max_threads();
#else
return 1;
#endif
}
inline int thread_num()
{
#ifdef _OPENMP
return omp_get_thread_num();
#else
return 0;
#endif
}
//==============================================================================
2018-12-15 15:34:00 -05:00
//! An object used to prevent concurrent access to a piece of data.
//
//! This type meets the C++ "Lockable" requirements.
//==============================================================================
2018-12-29 12:54:29 -05:00
class OpenMPMutex {
public:
void init()
2018-12-15 15:34:00 -05:00
{
#ifdef _OPENMP
2018-12-15 15:34:00 -05:00
omp_init_lock(&mutex_);
#endif
}
OpenMPMutex() { init(); }
2018-12-29 12:54:29 -05:00
~OpenMPMutex()
2018-12-15 15:34:00 -05:00
{
#ifdef _OPENMP
2018-12-15 15:34:00 -05:00
omp_destroy_lock(&mutex_);
#endif
}
2023-12-04 12:08:47 -06:00
// omp_lock_t objects cannot be deep copied, they can only be shallow
// copied. Thus, while shallow copying of an omp_lock_t object is
// completely valid (provided no race conditions exist), true copying
// of an OpenMPMutex object is not valid due to the action of the
// destructor. However, since locks are fungible, we can simply replace
// copying operations with default construction. This allows storage of
// OpenMPMutex objects within containers that may need to move/copy them
// (e.g., std::vector). It is left to the caller to understand that
// copying of OpenMPMutex does not produce two handles to the same mutex,
// rather, it produces two different mutexes.
// Copy constructor
OpenMPMutex(const OpenMPMutex& other) { init(); }
2023-12-04 12:08:47 -06:00
// Copy assignment operator
OpenMPMutex& operator=(const OpenMPMutex& other) { return *this; }
2018-12-15 15:34:00 -05:00
//! Lock the mutex.
//
//! This function blocks execution until the lock succeeds.
void lock()
2018-12-15 15:34:00 -05:00
{
#ifdef _OPENMP
2018-12-15 15:34:00 -05:00
omp_set_lock(&mutex_);
#endif
}
2018-12-15 15:34:00 -05:00
//! Try to lock the mutex and indicate success.
//
//! This function does not block. It returns immediately and gives false if
//! the lock is unavailable.
bool try_lock() noexcept
{
#ifdef _OPENMP
2018-12-15 15:34:00 -05:00
return omp_test_lock(&mutex_);
#else
return true;
#endif
}
2018-12-15 15:34:00 -05:00
//! Unlock the mutex.
void unlock() noexcept
{
#ifdef _OPENMP
2018-12-15 15:34:00 -05:00
omp_unset_lock(&mutex_);
#endif
}
private:
#ifdef _OPENMP
2018-12-15 15:34:00 -05:00
omp_lock_t mutex_;
#endif
};
} // namespace openmc
#endif // OPENMC_OPENMP_INTERFACE_H