diff --git a/include/GWcs.hpp b/include/GWcs.hpp index d472134..44e3741 100644 --- a/include/GWcs.hpp +++ b/include/GWcs.hpp @@ -30,6 +30,7 @@ /* __ Includes ___________________________________________________________ */ #include #include +#include #include #include "GSkyProjection.hpp" #include "GLog.hpp" @@ -37,6 +38,10 @@ #include "GSkyDir.hpp" #include "GSkyPixel.hpp" +#ifdef _OPENMP +#include +#endif + /***********************************************************************//** * @class GWcs @@ -220,6 +225,15 @@ protected: mutable GSkyDir m_last_dir2pix_dir; //!< Last sky direction for dir2pix mutable GSkyPixel m_last_pix2dir_pix; //!< Last pixel for pix2dir mutable GSkyPixel m_last_dir2pix_pix; //!< Last pixel for dir2pix + + // Thread locking + void init_lock(const int& lock_id=0) const; + void set_lock(const int& lock_id=0) const; + void unset_lock(const int& lock_id=0) const; + + #ifdef _OPENMP + mutable std::map m_locks; + #endif }; @@ -236,4 +250,49 @@ int GWcs::size(void) const return 2; } + +/***********************************************************************//** + * @brief Initializes an OpenMP lock with a specific name + * + * @param[in] lock_name Name of the lock that should be initialized + ***************************************************************************/ +inline +void GWcs::init_lock(const int& lock_id) const +{ + #ifdef _OPENMP + if (m_locks.count(lock_id) == 0) { + m_locks[lock_id] = omp_lock_t(); + omp_init_lock(&m_locks[lock_id]); + } + #endif +} + + +/***********************************************************************//** + * @brief Sets an OpenMP lock with a specific name + * + * @param[in] lock_name Name of the lock that should be set + ***************************************************************************/ +inline +void GWcs::set_lock(const int& lock_id) const +{ + #ifdef _OPENMP + omp_set_lock(&m_locks[lock_id]); + #endif +} + + +/***********************************************************************//** + * @brief Releases a previously set OpenMP lock + * + * @param[in] lock_name Name of the lock to be released + ***************************************************************************/ +inline +void GWcs::unset_lock(const int& lock_id) const +{ + #ifdef _OPENMP + omp_unset_lock(&m_locks[lock_id]); + #endif +} + #endif /* GWCS_HPP */ diff --git a/src/sky/GWcs.cpp b/src/sky/GWcs.cpp index 9d883f0..732bea0 100644 --- a/src/sky/GWcs.cpp +++ b/src/sky/GWcs.cpp @@ -678,13 +678,16 @@ GSkyDir GWcs::pix2dir(const GSkyPixel& pixel) const // the one used for the cache, then get the cached sky direction. We need // to put this in a OMP critical zone so that no other thread will change // the cache in the meantime - #pragma omp critical(GWcs_pix2dir_1) + bool update_cache = true; + set_lock(2); if (m_has_pix2dir_cache && (m_last_pix2dir_pix == pixel)) { dir = m_last_pix2dir_dir; + update_cache = false; } + unset_lock(2); // ... otherwise the computation of the sky direction is needed - else { + if (update_cache) { // Allocate memory for transformation double pixcrd[2]; @@ -712,12 +715,13 @@ GSkyDir GWcs::pix2dir(const GSkyPixel& pixel) const // Store result in cache. We need to put this in a OMP critical zone // to make sure that no other thread is fiddeling with the cache - #pragma omp critical(GWcs_pix2dir_2) + set_lock(2); { m_has_pix2dir_cache = true; m_last_pix2dir_pix = pixel; m_last_pix2dir_dir = dir; } + unset_lock(2); // Debug: Dump transformation steps #if defined(G_XY2DIR_DEBUG) @@ -758,13 +762,16 @@ GSkyPixel GWcs::dir2pix(const GSkyDir& dir) const // to the one used for the cache, then get the cached sky pixel. We need // to put this in a OMP critical zone so that no other thread will change // the cache in the meantime - #pragma omp critical(GWcs_dir2pix_1) + bool update_cache = true; + set_lock(1); if (m_has_dir2pix_cache && (m_last_dir2pix_dir == dir)) { pixel = m_last_dir2pix_pix; + update_cache = false; } + unset_lock(1); // ... otherwise the computation of the sky pixel is needed - else { + if (update_cache) { // Allocate memory for transformation double pixcrd[2]; @@ -793,12 +800,13 @@ GSkyPixel GWcs::dir2pix(const GSkyDir& dir) const // Store result in cache. We need to put this in a OMP critical zone // to make sure that no other thread is fiddeling with the cache - #pragma omp critical(GWcs_dir2pix_2) + set_lock(1); { m_has_dir2pix_cache = true; m_last_dir2pix_dir = dir; m_last_dir2pix_pix = pixel; } + unset_lock(1); // Debug: Dump transformation steps #if defined(G_DIR2XY_DEBUG) @@ -944,6 +952,12 @@ void GWcs::init_members(void) m_last_pix2dir_pix.clear(); m_last_dir2pix_pix.clear(); + // Initialize the locks + #ifdef _OPENMP + init_lock(1); + init_lock(2); + #endif + // Return return; }