''const static' STL container inside reentrant function
Let's say, that this is a function that serves several threads. They read kHKeys that is not protected since Read-Read from the same memory-address is not a data-race.
But, on the 1st Read, kHKeys is constructed. It is possible that during construction, another thread enters reentrantFunction function.
Is it necessary to construct kHKeys before unleashing the threads that call simultaneously the reentrantFunction ?
Example:
int reentrantFunction(const std::wstring& key_parent_c)
{
// const 'static' means that kHKeys is constructed only once —
// The 1st the function is run — and put into a shared memory space.
// Otherwise, kHKeys is local and it must be constructed each time the function is called.
const static std::map<std::wstring, HKEY> kHKeys{ { L"HKEY_CURRENT_USER", HKEY_CURRENT_USER } ,
{ L"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE } , { L"HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT } ,
{ L"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG } , { L"HKEY_CURRENT_USER_LOCAL_SETTINGS", HKEY_CURRENT_USER_LOCAL_SETTINGS } ,
{ L"HKEY_PERFORMANCE_DATA", HKEY_PERFORMANCE_DATA } , { L"HKEY_PERFORMANCE_NLSTEXT", HKEY_PERFORMANCE_NLSTEXT } ,
{ L"HKEY_PERFORMANCE_TEXT", HKEY_PERFORMANCE_TEXT } , { L"HKEY_USERS", HKEY_USERS } };
// Use kHKeys
Solution 1:[1]
As requested a separate answer about constructing STL containers at compile time:
Note that some STL containers are now constexpr and the compiler might construct the value at compile time and place it in the .data section. You can (try to) force that by declaring it constinit.
As an example lets create an array of the first 5 primes:
#include <string>
#include <array>
constexpr std::array<int, 5> make_primes() {
std::array<int, 5> v;
for (int i = 0, j = 2; i < 5; ++j) {
for(int k = 2; k < j; ++k) {
if (j % k == 0) {
continue;
}
}
v[i++] = j;
}
return v;
}
int bla(int i)
{
static constinit std::array<int, 5> primes = make_primes();
return primes[i];
}
This results in the following code: https://godbolt.org/z/a5h6TE9f7
bla(int):
movsx rdi, edi
mov eax, DWORD PTR bla(int)::primes[0+rdi*4]
ret
bla(int)::primes:
.long 2
.long 3
.long 4
.long 5
.long 6
As you can see nowhere in the compiled code are any primes calculated. That happened at compile time and the resulting std::array is placed in the data section (section not visible).
Because I used constinit the compiler will fail if the variable can not be computed at compile time. If I had used constexpr the compiler would try to compute the value a compile time but might decide the computation is to expensive at compile time and initialize the variable at run time.
Solution 2:[2]
You can store your breakpoints in a list and use a @each loop:
$breakpoints: sm, md, lg, xl, xxl;
@for $i from 1 through 200 {
.m-#{$i}px {
margin: 1px * $i !important;
@each $breakpoint in $breakpoints {
&-#{$breakpoint} {
@include media-breakpoint-up($breakpoint) {
margin: 1px * $i !important;
}
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Goswin von Brederlow |
| Solution 2 | Arkellys |
