mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-21 06:25:30 -04:00
65 lines
2.1 KiB
C++
65 lines
2.1 KiB
C++
#ifndef OPENMC_NEIGHBOR_LIST_H
|
|
#define OPENMC_NEIGHBOR_LIST_H
|
|
|
|
#include <algorithm>
|
|
#include <cstdint>
|
|
#include <forward_list>
|
|
#include <mutex>
|
|
|
|
#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<value_type>::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<OpenMPMutex> 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<value_type> list_;
|
|
OpenMPMutex mutex_;
|
|
};
|
|
|
|
} // namespace openmc
|
|
#endif // OPENMC_NEIGHBOR_LIST_H
|