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

openmc-dev / openmc / 26141145931

20 May 2026 04:23AM UTC coverage: 81.469% (+0.09%) from 81.382%
26141145931

push

github

web-flow
Shared Secondary Particle Bank (#3863)

Co-authored-by: John Tramm <jtramm@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Paul Romano <paul.k.romano@gmail.com>
Co-authored-by: Copilot <copilot@github.com>

17952 of 25878 branches covered (69.37%)

Branch coverage included in aggregate %.

416 of 428 new or added lines in 17 files covered. (97.2%)

4 existing lines in 4 files now uncovered.

59057 of 68647 relevant lines covered (86.03%)

48565468.2 hits per line

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

80.36
/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 <algorithm> // for copy_n
8

9
#include "openmc/memory.h"
10

11
namespace openmc {
12

13
//==============================================================================
14
// Class declarations
15
//==============================================================================
16

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

28
public:
29
  //==========================================================================
30
  // Constructors
31

32
  //! Default constructor.
33
  SharedArray() = default;
8,656✔
34

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

43
  //==========================================================================
44
  // Methods and Accessors
45

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

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

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

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

85
    // Copy element value to the array
86
    data_[idx] = value;
612,789,056✔
87

88
    return idx;
612,789,056✔
89
  }
90

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

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

117
  //! Return the number of elements in the container
118
  int64_t size() { return size_; }
186,426,501!
119
  int64_t size() const { return size_; }
120

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

128
  //! Return whether the array is full
129
  bool full() const { return size_ == capacity_; }
2,147,483,647✔
130

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

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

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

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

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

154
} // namespace openmc
155

156
#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