immutable, static, __gshared, TLS, and compile time allocation

Jonathan M Davis jmdavisProg at gmx.com
Fri Apr 20 15:48:04 PDT 2012


On Saturday, April 21, 2012 00:50:39 Manu wrote:
> On 21 April 2012 00:05, Jonathan M Davis <jmdavisProg at gmx.com> wrote:
> > On Friday, April 20, 2012 23:45:11 Manu wrote:
> > static immutable x; <- i've seen this a few times, what does it mean?
> > 
> > Assuming that static is valid in that context, it means that you have a
> > static
> > variable which is immutable. If it's not valid (e.g. module-level
> > variable),
> > then it's just an immutable variable. In either case, because it's
> > immutable,
> > it's implicitly shared.
> 
> Implicitly 'shared', or implicitly '__gshared'? .. In this case, there
> should be no practical difference, but 'shared' comes loaded with some
> other bonuses that claim it may perform auto-locking when it is accessed,
> which is obviously not necessary for anything immutable.

It's implicitly shared across threads. I'm not sure that it's really either 
shared or __gshared. Any protections that shared has which would be applicable 
to immutable would certainly be on it though. However, many of them aren't 
properly implemented on shared yet anyway. It's just that because you can't 
ever assign to an immutable variable after initializing it, it's safe for the 
compiler to not put in TLS. Certainly, whenever it's discussed, it's stated 
that immutable is implicitly shared and _not_ that it's implicitly __gshared. 
I don't think that I've ever seen __gshared come up in a discussion on 
immutable before.

One place where the sharing of immutable becomes evident is in

http://d.puremagic.com/issues/show_bug.cgi?id=6114

It should be illegal to initialize immutable module-level and immutable static 
variables in non-static constructors, but it isn't at present. So if you do, 
you can actually initialize immutable variables multiple times (which 
obviously good). Presumably, it'll be fixed at some point though. Regardless, 
it shows how immutable variables aren't put in TLS.

> > There's another thing that that's had me scratching my head for a while,
> > 
> > > and gave me the contradictory feeling that the use of TLS data is fairly
> > > relaxed:
> > > 
> > > struct S
> > > {
> > > int x;
> > > static int y;
> > > }
> > > 
> > > In this case y is static, ie, globally shared by all instances, but I
> > > expect it SHOULD be TLS, since it is mutable, and therefore not thread
> > > safe...
> > > That said, I write code that passes static members of structs into
> > > templates as alias parameters all the time, and generate code that
> > > writes
> > > to them.
> > > How is this possible? And given that it is, why is it not possible for
> > > at
> > > least __gshared at global scope?
> > 
> > I don't understand the problem. y is static, so there's a single instance
> > for
> > it for the class *per thread*, whereas each instance of S will have its
> > own x. I
> > think that I'd have to see actual code to understand exactly what your
> > issue
> > is with regard to templates.
> 
> I think you've missed my point. If y is TLS, then it's location can't be
> known at compile time, in which case, how is it possible to supply it an an
> alias template parameter?
> And given that it IS possible, I don't understand why it is not possible to
> alias something that is __gshared.
> 
> This is the main thing I'm trying to understand.
> What mechanisms affect whether the compiler knows the address of
> static/global/shared variables at compile time or not? TLS being the
> obvious one, but that seems to contradict observation in both cases here.

Please give code examples. I'm much more likely to understand what you mean 
that way.

> > struct S
> > 
> > > {
> > > static x;
> > > __gshared y;
> > > }
> > > 
> > > What is the difference between x and y here?
> > 
> > x is in TLS, so there's one instance per thread. I'm not quite sure
> > whether
> > __gshared does anything here though, since it's a member variable rather
> > than
> > a class variable or module-level variable. I expect that __gshared is
> > ignored
> > here, but I don't know. If you had
> > 
> > struct S
> > {
> > 
> > static x;
> > static __gshared y;
> > 
> > }
> > 
> > then there would be one instance of y for the entire program, but it
> > wouldn't
> > be protected in the same way that it would be if it were shared.
> 
> But the documentation for __gshared states that this is not necessary, it
> says quite clearly that __gshared is the same as 'static' in this context,
> but that doesn't make sense, since static should be TLS, but __gshared is
> not...

static shouldn't have anything to do with TLS beyond the fact that it doesn't 
make any sense for a non-static member variable to be marked as shared or 
__gshared, since whether it's in TLS or not is determined whether the object 
that it's in is TLS or not.

In the case of a struct or class, static merely states that there's only one 
instance per class/struct rather than it being a member variable, not anything 
about TLS. And if the documentation states that the static is implied for 
__gshared (I haven't read it recently), then that that just means that 
__gshared is always static so that you don't get the weird situation where you 
have a __gshared member variable (which would be meaningless as far as I can 
tell).

- Jonathan M Davis


More information about the Digitalmars-d mailing list