• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openmc-dev / openmc / 23020451435

12 Mar 2026 07:39PM UTC coverage: 81.638% (+0.07%) from 81.566%
23020451435

Pull #3863

github

web-flow
Merge 5541c0bf0 into 27522fe85
Pull Request #3863: Shared Secondary Particle Bank

17761 of 25507 branches covered (69.63%)

Branch coverage included in aggregate %.

418 of 435 new or added lines in 17 files covered. (96.09%)

10 existing lines in 4 files now uncovered.

58266 of 67620 relevant lines covered (86.17%)

46325054.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.87
/include/openmc/shared_array.h
1
#ifndef OPENMC_SHARED_ARRAY_H
2
#define OPENMC_SHARED_ARRAY_H
3

4
//! \file shared_array.h
5
//! \brief Shared array data structure
6

7
#include "openmc/memory.h"
8

9
namespace openmc {
10

11
//==============================================================================
12
// Class declarations
13
//==============================================================================
14

15
// This container is an array that is capable of being appended to in an
16
// thread safe manner by use of atomics. It only provides protection for the
17
// use cases currently present in OpenMC. Namely, it covers the scenario where
18
// multiple threads are appending to an array, but no threads are reading from
19
// or operating on it in any other way at the same time. Multiple threads can
20
// call the thread_safe_append() function concurrently and store data to the
21
// object at the index returned from thread_safe_append() safely, but no other
22
// operations are protected.
23
template<typename T>
24
class SharedArray {
11,795!
25

26
public:
27
  //==========================================================================
28
  // Constructors
29

30
  //! Default constructor.
31
  SharedArray() = default;
8,635✔
32

33
  //! Construct a container with size elements, with space to hold size number
34
  //! of elements.
35
  //
36
  //! \param size The number of elements to allocate and initialize
37
  SharedArray(int64_t size) : size_(size), capacity_(size)
3,160✔
38
  {
39
    data_ = make_unique<T[]>(size);
3,160!
40
  }
3,160!
41

42
  //==========================================================================
43
  // Methods and Accessors
44

45
  //! Return a reference to the element at specified location i. No bounds
46
  //! checking is performed.
47
  T& operator[](int64_t i) { return data_[i]; }
314,121,412✔
48
  const T& operator[](int64_t i) const { return data_[i]; }
49

50
  //! Allocate space in the container for the specified number of elements.
51
  //! reserve() does not change the size of the container.
52
  //
53
  //! \param capacity The number of elements to allocate in the container
54
  void reserve(int64_t capacity)
7,129✔
55
  {
56
    data_ = make_unique<T[]>(capacity);
7,751!
57
    capacity_ = capacity;
7,129✔
58
  }
7,129✔
59

60
  //! Increase the size of the container by one and append value to the
61
  //! array. Returns an index to the element of the array written to. Also
62
  //! tests to enforce that the append operation does not read off the end
63
  //! of the array. In the event that this does happen, set the size to be
64
  //! equal to the capacity and return -1.
65
  //
66
  //! \value The value of the element to append
67
  //! \return The index in the array written to. In the event that this
68
  //! index would be greater than what was allocated for the container,
69
  //! return -1.
70
  int64_t thread_safe_append(const T& value)
604,406,739✔
71
  {
72
    // Atomically capture the index we want to write to
73
    int64_t idx;
74
#pragma omp atomic capture seq_cst
540,012,429✔
75
    idx = size_++;
604,406,739✔
76

77
    // Check that we haven't written off the end of the array
78
    if (idx >= capacity_) {
604,406,739!
79
#pragma omp atomic write seq_cst
80
      size_ = capacity_;
UNCOV
81
      return -1;
×
82
    }
83

84
    // Copy element value to the array
85
    data_[idx] = value;
604,406,739✔
86

87
    return idx;
604,406,739✔
88
  }
89

90
  //! Free any space that was allocated for the container. Set the
91
  //! container's size and capacity to 0.
92
  void clear()
44,865✔
93
  {
94
    data_.reset();
44,865✔
95
    size_ = 0;
44,865✔
96
    capacity_ = 0;
44,865✔
97
  }
44,865✔
98

99
  //! Push back an element to the array, with capacity and reallocation behavior
100
  //! as if this were a vector. This does not perform any thread safety checks.
101
  //! If the size exceeds the capacity, then the capacity will double just as
102
  //! with a vector. Data will be reallocated and moved to a new pointer and
103
  //! copied in before the new item is appended. Old data will be freed.
104
  void thread_unsafe_append(const T& value)
21,354,077✔
105
  {
106
    if (size_ == capacity_) {
21,354,077✔
107
      int64_t new_capacity = capacity_ == 0 ? 1 : 2 * capacity_;
72,465✔
108
      unique_ptr<T[]> new_data = make_unique<T[]>(new_capacity);
72,465✔
109
      for (int64_t i = 0; i < size_; i++) {
29,196,176✔
110
        new_data[i] = std::move(data_[i]);
29,123,711✔
111
      }
112
      data_ = std::move(new_data);
72,465✔
113
      capacity_ = new_capacity;
72,465!
114
    }
72,465✔
115
    data_[size_++] = value;
21,354,077✔
116
  }
21,354,077✔
117

118
  //! Return the number of elements in the container
119
  int64_t size() { return size_; }
178,026,664!
120
  int64_t size() const { return size_; }
121

122
  //! Resize the container to contain a specified number of elements. This is
123
  //! useful in cases where the container is written to in a non-thread safe
124
  //! manner, where the internal size of the array needs to be manually updated.
125
  //
126
  //! \param size The new size of the container
127
  void resize(int64_t size) { size_ = size; }
3,924,914✔
128

129
  //! Return whether the array is full
130
  bool full() const { return size_ == capacity_; }
1,285,977,517✔
131

132
  //! Return the number of elements that the container has currently allocated
133
  //! space for.
134
  int64_t capacity() { return capacity_; }
94,300✔
135

136
  //! Return pointer to the underlying array serving as element storage.
137
  T* data() { return data_.get(); }
190,431✔
138
  const T* data() const { return data_.get(); }
139

140
  //! Classic iterators
141
  T* begin() { return data_.get(); }
1,159✔
142
  const T* cbegin() const { return data_.get(); }
143
  T* end() { return data_.get() + size_; }
144
  const T* cend() const { return data_.get() + size_; }
145

146
private:
147
  //==========================================================================
148
  // Data members
149

150
  unique_ptr<T[]> data_; //!< An RAII handle to the elements
151
  int64_t size_ {0};     //!< The current number of elements
152
  int64_t capacity_ {0}; //!< The total space allocated for elements
153
};
154

155
} // namespace openmc
156

157
#endif // OPENMC_SHARED_ARRAY_H
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc