C++ Logo

liaison

Advanced search

Re: [wg14/wg21 liaison] On _Thread_local for better C++ interoperability with C (P2478)

From: Uecker, Martin <Martin.Uecker_at_[hidden]>
Date: Sat, 12 Feb 2022 10:27:16 +0000
Am Samstag, den 12.02.2022, 11:21 +0100 schrieb Martin Uecker:
> Am Samstag, den 12.02.2022, 11:09 +0100 schrieb Corentin via Liaison:
> > On Sat, Feb 12, 2022 at 12:09 AM Jens Maurer <Jens.Maurer_at_gmx.net> wrote:
> >
> > > On 11/02/2022 23.54, Corentin wrote:
> > > > Su
> > > >
> > > > On Fri, Feb 11, 2022 at 10:44 PM Jens Maurer <Jens.Maurer_at_gmx.net
> > > <mailto:Jens.Maurer_at_[hidden]>> wrote:
> > > > On 11/02/2022 22.39, Corentin wrote:
> > > > >
> > > > >
> > > > > On Fri, Feb 11, 2022 at 10:33 PM Jens Maurer <Jens.Maurer_at_gmx.net
> > > <mailto:Jens.Maurer_at_gmx.net> <mailto:Jens.Maurer_at_gmx.net <mailto:
> > > Jens.Maurer_at_[hidden]>>> wrote:
> > > > >
> > > > > On 11/02/2022 22.20, Corentin via Liaison wrote:
> > > > >
> > > > > >
> > > > > > I think the most intuitive behavior is if
> > > > > >
> > > > > > extern "C" thread_local S foo;
> > > > > >
> > > > > > behaves just like _Thread_local would do in C and a
> > > C++ type
> > > > > > that requires non-trivial initialization would
> > > simply not
> > > > > > be allowed, i.e. it behaves like _Thread_local in
> > > clang
> > > > > > in c++ mode.
> > > > >
> > > > > Sounds good to me.
> > > > >
> > > > > - Survives WG14 making thread_local a real keyword.
> > > > >
> > > > > - Requires no collaboration from WG14.
> > > > >
> > > > > - Your header shared between C++ and C already ought to use
> > > 'extern "C"',
> > > > > so this reduces the footgun surface.
> > > > >
> > > > > - thread_local in C++ with dynamic libraries is already a
> > > nightmare
> > > > > (dynamic initialization order, squared), and this nicely
> > > sidesteps the
> > > > > problem.
> > > > >
> > > > > - If C++ wants to do something on the C++ side (e.g.
> > > constdestroy or so),
> > > > > it can do so at its own pace.
> > > > >
> > > > > > I agree. Why would you be trying to use a type with
> > > non-trivial init in common code defined in a header, but so that it does
> > > different things in C and C++? If you need non-trivial init, define the
> > > code in a separate C++ transition unit, not in a header.
> > > > > >
> > > > > >
> > > > > > But by that logic, do we want to change the grammar of C++
> > > for this narrow scenario?
> > > > >
> > > > > We're not changing the grammar. We're just adding a paragraph
> > > of restrictions
> > > > > for thread_local. That seems palatable, given that 'extern
> > > "C"' already
> > > > > causes restrictions for other areas of the C++ syntax.
> > > > >
> > > > >
> > > > > Don't we need to allow extern "C" static? Afaict this would be
> > > novel
> > > > extern "C" {
> > > > static int x = 1;
> > > > }
> > > >
> > > > works with gcc today.
> > > >
> > > >
> > > > How do you handle local static at function scope?
> > > If you want to use the surrounding function from both C and C++,
> > > you need to wrap it into "extern C" (simply to get the correct name
> > > mangling) and the thread_local thus appears within extern C and the
> > > novel semantics apply.
> > >
> > > If you want to use the function from C++ only, it's likely not wrapped
> > > in "extern C" and you get the usual C++ semantics.
> > >
> >
> > My understanding of the issue was as follows:
> > There is a thread_local which is a C++ type (thereby not extern) , passed
> > to a C function, from within a C++ function.
> > Such thread_local could be declared at function scope.
> >
> > struct S {
> > S();
> > };
> >
> > extern "C" {
> > void foo(S*);
> > static thread_local S s; // would be okay, with different semantics (eager
> > initialization)
> > };
> >
> >
> > void f() {
> > /* extern "C" */ static thread_local S s; // Do we care to support that ?
> > foo(&s);
> > }
> >
> >
> > Here I don't think users will necessarily want to put f in the extern "C"
> > scope, for example.
> > The variable needs to be in an extern "C" scope, not necessarily the
> > enclosing function
>
> Is this a problem? My understanding was that C++ compiler would have
> to initialize the variable at that point anyway. Whether a C or C++
> functions is called does not matter, because in neither case the
> function could know that this is a tread_local variable, and so
> the initialization has to be invoked in both case.

If I am not missing something, this case would just work anyway:

https://godbolt.org/z/vn3xdKKe7

Martin


Received on 2022-02-12 10:27:20