ImpactX
Toggle main menu visibility
Loading...
Searching...
No Matches
src
elements
mixin
dynamicdata.H
Go to the documentation of this file.
1
/* Copyright 2022-2026 The Regents of the University of California, through Lawrence
2
* Berkeley National Laboratory (subject to receipt of any required
3
* approvals from the U.S. Dept. of Energy). All rights reserved.
4
*
5
* This file is part of ImpactX.
6
*
7
* Authors: Axel Huebl
8
* License: BSD-3-Clause-LBNL
9
*/
10
#ifndef IMPACTX_ELEMENTS_MIXIN_DYNAMICDATA_H
11
#define IMPACTX_ELEMENTS_MIXIN_DYNAMICDATA_H
12
13
#include "impactx_export.H"
14
15
#include <
AMReX_Gpu.H
>
16
17
#include <map>
18
#include <memory>
19
#include <stdexcept>
20
#include <string>
21
#include <type_traits>
22
#include <vector>
23
24
25
namespace
impactx::elements::mixin
26
{
27
52
template
<
typename
T>
53
struct
GPUDataRegistry
54
{
55
using
DataType
= T;
56
57
// Storage for the registry's state.
58
//
59
// Declared here as plain `static` members and defined out-of-line below
60
// (rather than `inline static ... = init;`) for two reasons:
61
//
62
// 1. NVCC 12.2 + C++20 evaluates the default-initializer of an
63
// `inline static` data member during implicit instantiation of the
64
// enclosing class template (any reference such as
65
// `DynamicData::get(id)` from an element header triggers it). With
66
// a `std::map<int, std::shared_ptr<T>>` value type that fails as
67
// "incomplete type is not allowed" on the brace-initializer. A
68
// declaration with no initializer sidesteps this entirely; the
69
// out-of-line definitions are only processed when an explicit
70
// instantiation actually requests them.
71
// 2. Combined with `extern template struct` in element headers and
72
// `template struct` in the corresponding .cpp, this still provides
73
// exactly one strong definition per element type. With
74
// `IMPACTX_EXPORT` the resulting symbol has default visibility, so
75
// downstream shared libraries built with `-fvisibility=hidden`
76
// and/or LTO (e.g. the Python bindings module) resolve to that one
77
// definition at load time even if they re-instantiate the
78
// `emplace<Args...>` member template locally. The previous
79
// function-local-static design (PR #1368) produced a hidden
80
// duplicate per DSO via the inlined accessor body inside `emplace`
81
// and caused emplace/get to disagree across module boundaries.
82
IMPACTX_EXPORT
static
int
s_next_id
;
83
IMPACTX_EXPORT
static
std::map<int, std::shared_ptr<T>>
s_registry
;
84
85
static
int
&
next_id
() {
return
s_next_id
; }
86
static
std::map<int, std::shared_ptr<T>>&
registry
() {
return
s_registry
; }
87
89
static
int
allocate_id
() {
return
next_id
()++; }
90
97
static
std::shared_ptr<T>
const
&
98
get
(
int
id
)
99
{
100
auto
& reg =
registry
();
101
auto
it = reg.find(
id
);
102
if
(it == reg.end() || !it->second)
103
throw
std::runtime_error(
104
"GPUDataRegistry::get failed for id="
+ std::to_string(
id
));
105
return
it->second;
106
}
107
113
static
void
store
(
int
id
, std::shared_ptr<T> data)
114
{
115
registry
()[id] = std::move(data);
116
}
117
124
template
<
typename
... Args>
125
static
T&
emplace
(
int
id
, Args&&... args)
126
{
127
auto
ptr = std::shared_ptr<T>(
new
T{std::forward<Args>(args)...});
// NOLINT(modernize-make-shared)
128
registry
()[id] = ptr;
129
return
*ptr;
130
}
131
133
static
void
clear
()
134
{
135
registry
().clear();
136
next_id
() = 0;
137
}
138
};
139
140
// Out-of-class template definitions for the static data members declared
141
// inside `GPUDataRegistry`. These are deliberately not `inline static
142
// ... = init;` inside the class: see the comment on the declarations for
143
// the NVCC 12.2 + C++20 reason. Each element type gets exactly one strong
144
// definition per program via `IMPACTX_GPUDATA_INSTANTIATE` in its .cpp.
145
template
<
typename
T>
146
int
GPUDataRegistry<T>::s_next_id
= 0;
147
148
template
<
typename
T>
149
std::map<int, std::shared_ptr<T>>
GPUDataRegistry<T>::s_registry
;
150
151
}
// namespace impactx::elements::mixin
152
153
169
#define IMPACTX_GPUDATA_EXTERN(ElementType) \
170
extern template struct impactx::elements::mixin::GPUDataRegistry< \
171
ElementType::DynamicData::DataType>;
172
180
#define IMPACTX_GPUDATA_INSTANTIATE(ElementType) \
181
template struct impactx::elements::mixin::GPUDataRegistry< \
182
ElementType::DynamicData::DataType>;
183
184
#endif
// IMPACTX_ELEMENTS_MIXIN_DYNAMICDATA_H
AMReX_Gpu.H
impactx::elements::mixin
Definition
alignment.H:25
impactx::elements::mixin::GPUDataRegistry
Definition
dynamicdata.H:54
impactx::elements::mixin::GPUDataRegistry::store
static void store(int id, std::shared_ptr< T > data)
Definition
dynamicdata.H:113
impactx::elements::mixin::GPUDataRegistry< CFbendCoefficients >::s_registry
static IMPACTX_EXPORT std::map< int, std::shared_ptr< CFbendCoefficients > > s_registry
Definition
dynamicdata.H:83
impactx::elements::mixin::GPUDataRegistry::registry
static std::map< int, std::shared_ptr< T > > & registry()
Definition
dynamicdata.H:86
impactx::elements::mixin::GPUDataRegistry::get
static std::shared_ptr< T > const & get(int id)
Definition
dynamicdata.H:98
impactx::elements::mixin::GPUDataRegistry::allocate_id
static int allocate_id()
Definition
dynamicdata.H:89
impactx::elements::mixin::GPUDataRegistry::emplace
static T & emplace(int id, Args &&... args)
Definition
dynamicdata.H:125
impactx::elements::mixin::GPUDataRegistry::next_id
static int & next_id()
Definition
dynamicdata.H:85
impactx::elements::mixin::GPUDataRegistry< CFbendCoefficients >::DataType
CFbendCoefficients DataType
Definition
dynamicdata.H:55
impactx::elements::mixin::GPUDataRegistry< CFbendCoefficients >::s_next_id
static IMPACTX_EXPORT int s_next_id
Definition
dynamicdata.H:82
impactx::elements::mixin::GPUDataRegistry::clear
static void clear()
Definition
dynamicdata.H:133
Generated by
1.17.0