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

openmc-dev / openmc / 29158451936

11 Jul 2026 03:43PM UTC coverage: 81.294% (-0.007%) from 81.301%
29158451936

Pull #4011

github

web-flow
Merge 901449abe into e783e0147
Pull Request #4011: Performance optimizations for shared secondary bank

18229 of 26454 branches covered (68.91%)

Branch coverage included in aggregate %.

57 of 62 new or added lines in 2 files covered. (91.94%)

1 existing line in 1 file now uncovered.

59470 of 69124 relevant lines covered (86.03%)

48447029.94 hits per line

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

83.21
/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 {
20,048!
27

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

32
  //! Default constructor.
33
  SharedArray() = default;
16,888✔
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,868,397✔
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,709✔
56
  {
57
    data_ = make_unique<T[]>(capacity);
8,622!
58
    capacity_ = capacity;
7,709✔
59
  }
7,709✔
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)
613,614,970✔
72
  {
73
    // Atomically capture the index we want to write to
74
    int64_t idx;
75
#pragma omp atomic capture seq_cst
545,410,652✔
76
    idx = size_++;
613,614,970✔
77

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

85
    // Copy element value to the array
86
    data_[idx] = value;
613,614,969✔
87

88
    return idx;
613,614,969✔
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()
47,763✔
94
  {
95
    data_.reset();
47,763✔
96
    size_ = 0;
47,763✔
97
    capacity_ = 0;
47,763✔
98
  }
47,763✔
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)
106
  {
107
    if (size_ == capacity_) {
108
      int64_t new_capacity = capacity_ == 0 ? 8 : 2 * capacity_;
109
      unique_ptr<T[]> new_data = make_unique<T[]>(new_capacity);
110
      std::copy_n(data_.get(), size_, new_data.get());
111
      data_ = std::move(new_data);
112
      capacity_ = new_capacity;
113
    }
114
    data_[size_++] = value;
115
  }
116

117
  //! Increase the size of the container by count elements without assigning
118
  //! values to the new elements. Existing elements are preserved if the
119
  //! container needs to grow. This does not perform any thread safety checks.
120
  //
121
  //! \param count The number of elements to append
122
  //! \return The starting index of the appended range
123
  int64_t extend_uninitialized(int64_t count)
9,314✔
124
  {
125
    int64_t offset = size_;
9,314✔
126
    int64_t new_size = size_ + count;
9,314✔
127
    if (new_size > capacity_) {
9,314✔
128
      int64_t new_capacity = capacity_ == 0 ? 8 : capacity_;
2,404✔
129
      while (new_capacity < new_size) {
9,198✔
130
        new_capacity *= 2;
6,794✔
131
      }
132
      unique_ptr<T[]> new_data = make_unique<T[]>(new_capacity);
2,404✔
133
      if (size_ > 0) {
2,404!
NEW
134
        std::copy_n(data_.get(), size_, new_data.get());
×
135
      }
136
      data_ = std::move(new_data);
2,404✔
137
      capacity_ = new_capacity;
2,404!
138
    }
2,404✔
139
    size_ = new_size;
9,314✔
140
    return offset;
9,314✔
141
  }
142

143
  //! Return the number of elements in the container
144
  int64_t size() { return size_; }
165,291,803!
145
  int64_t size() const { return size_; }
146

147
  //! Resize the container to contain a specified number of elements. This is
148
  //! useful in cases where the container is written to in a non-thread safe
149
  //! manner, where the internal size of the array needs to be manually updated.
150
  //
151
  //! \param size The new size of the container
152
  void resize(int64_t size) { size_ = size; }
3,958,469✔
153

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

157
  //! Return the number of elements that the container has currently allocated
158
  //! space for.
159
  int64_t capacity() { return capacity_; }
94,709✔
160

161
  //! Return pointer to the underlying array serving as element storage.
162
  T* data() { return data_.get(); }
198,751✔
163
  const T* data() const { return data_.get(); }
164

165
  //! Classic iterators
166
  T* begin() { return data_.get(); }
1,347✔
167
  const T* cbegin() const { return data_.get(); }
168
  T* end() { return data_.get() + size_; }
169
  const T* cend() const { return data_.get() + size_; }
170

171
private:
172
  //==========================================================================
173
  // Data members
174

175
  unique_ptr<T[]> data_; //!< An RAII handle to the elements
176
  int64_t size_ {0};     //!< The current number of elements
177
  int64_t capacity_ {0}; //!< The total space allocated for elements
178
};
179

180
} // namespace openmc
181

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