3

Consider the below testcase:

#include <iostream>
#include <thread>

thread_local struct Bar
{
     Bar() { std::cout << '*' << std::endl; }
    ~Bar() { std::cout << '~' << std::endl; }
} bar;

struct Foo
{
    void baz()
    {
        (void)&bar;
    }
};

int main()
{
    Foo f;
    f.baz();

    std::thread t(&Foo::baz, &f);
    t.join();
}

On Coliru it works as I intend, with the seemingly useless statement (void)&bar apparently counting as "use" and ensuring that bar is constructed in any thread that invokes baz().

Is this guaranteed, or should I do something more?

I'm hoping to use a class like Bar to wrap some per-thread initialisation required by a C library I'm going to use, with a minimum of boilerplate. baz() is already a function that any thread will call to do work with the C library, so this could effectively be a transparent solution.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Taking the address is _odr-use_ but I'm concerned about potentially permitted optimisations, given that I literally never do anything with the object, despite the side effects of construction and destruction (let's face it, there are examples of exceptions to that in the language) – Lightness Races in Orbit Feb 07 '18 at 18:49
  • Since the constructor of Bar gets called, there's no way any optimizer will remove that statement. – huysentruitw Feb 07 '18 at 18:50
  • 1
    @WouterHuysentruit: It's a little more complicated than just looking at the declaration and saying the constructor gets called: remove `(void)&b` and you'll find that it isn't. The guarantee I'm looking for is that adding `(void)&b` back in ensures that it _is_. – Lightness Races in Orbit Feb 07 '18 at 18:51
  • 3
    I asked something similar [here](https://stackoverflow.com/questions/24253584/when-is-a-thread-local-global-variable-initialized). The standard guarantees that a thread-local is initialized before its first odr-use, and `&bar` is indeed an ODR-use. Am I missing something? – sbabbi Feb 07 '18 at 18:57
  • I was indeed referring to the `(void)&bar` statement, which you shouldn't remove of course. – huysentruitw Feb 07 '18 at 18:58
  • @sbabbi: If that's so, then I don't think you're missing anything :) – Lightness Races in Orbit Feb 07 '18 at 20:56

0 Answers0