forked from openmc-dev/openmc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathneighbor_list.h
65 lines (55 loc) · 2.15 KB
/
neighbor_list.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#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