On 23.03.2020 10:45, Frederick Gotham wrote:
>
> If the amount of threads I want to create is a constexpr, but if this constexpr can be changed between compilations (for example from 3 to 4 depending on the platform), and if I don't want to allocate the "std::thread" objects on the heap, then is there a better way to do it than the following?
>
> auto main(void) -> int
> {
> array<aligned_union<0,thread>::type, g_N_threads> storage_for_threads;
>
> for ( unsigned i = 0; i != g_N_threads; ++i )
> {
> ::new(&storage_for_threads[i]) thread(EntryPoint, i);
> }
You said that you don't want to allocate thread objects on heap, but
why? Is this some obsession about saving a nanosecond at the start of
the program?
Is your program meant for high-frequency trading at NYSE? No? Then
what's wrong with a std::vector<std::thread>?
I would understand this if you said this is about learning placement new
and implementing one's own containers from scratch. However, for holding
thread objects this does not make any sense as thread creation is anyway
a massively expensive operation when compared to a dynamic memory
allocation.
>
> /* Do stuff */
>
> for ( unsigned i = 0; i != g_N_threads; ++i )
> {
> thread &t = *reinterpret_cast<thread*>(&storage_for_threads[i]);
You should avoid reinterpret_cast if possible, it's not well-behaved in
general.
In this example you should either remember the addresses returned by
placement new, or use std::launder() for making the result pointer legal
(std::launder is meant for low-level container implementers, if you
insist on doing that you need to learn about it).