#ifndef OPENMC_NEIGHBOR_LIST_H #define OPENMC_NEIGHBOR_LIST_H #include #include #include #include #include "openmc/openmp_interface.h" namespace openmc { //============================================================================== //! A threadsafe, dynamic container for listing neighboring cells. // //! This container is a reduced interface for a linked list with an added OpenMP //! lock for write operations. It allows for threadsafe dynamic growth; any //! number of threads can safely read data without locks or reference counting. //============================================================================== class NeighborList { public: using value_type = int32_t; using const_iterator = std::forward_list::const_iterator; // Attempt to add an element. // // If the relevant OpenMP lock is currently owned by another thread, this // function will return without actually modifying the data. It has been // found that returning the transport calculation and possibly re-adding the // element later is slightly faster than waiting on the lock to be released. void push_back(int new_elem) { // Try to acquire the lock. std::unique_lock lock(mutex_, std::try_to_lock); if (lock) { // It is possible another thread already added this element to the list // while this thread was searching for a cell so make sure the given // element isn't a duplicate before adding it. if (std::find(list_.cbegin(), list_.cend(), new_elem) == list_.cend()) { // Find the end of the list and add the the new element there. if (!list_.empty()) { auto it1 = list_.cbegin(); auto it2 = ++list_.cbegin(); while (it2 != list_.cend()) it1 = it2++; list_.insert_after(it1, new_elem); } else { list_.push_front(new_elem); } } } } const_iterator cbegin() const { return list_.cbegin(); } const_iterator cend() const { return list_.cend(); } private: std::forward_list list_; OpenMPMutex mutex_; }; } // namespace openmc #endif // OPENMC_NEIGHBOR_LIST_H