www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - [static] [shared] [const|immutable]

reply "Lionello Lunesu" <lionello lunesu.remove.com> writes:
I like shared/const/immutable as much as the next guy, but there are now 
2x2x3=12 ways to decorate a variable. Furthermore, by either declaring the 
variable globally or locally (stack), we end up with 24 possible 
declaration. See the code at the end of this post.

Surely, some combinations should/can be disallowed?
 * What's the point of "shared immutable"?
 * What about a locally declared "shared" variable? (The stack is implicit 
TLS anyway.)
 * Come to think of it, what's the difference between a "const int" and a 
"immutable int"? (Is "const" only meant to be used in a function's argument 
list?)

L.

(From the results it's apparent that "static" on the global level does not 
actually do anything (probably kept for C/C++ compatibility where it's used 
to mean "private") and that "static" used locally declares the variable as 
if it were global. This makes sense.)

//The code:

int f = 0xDEAD0001;     //0678
const int cf = 0xDEAD0002;    //068d
immutable int _if = 0xDEAD0003;    //068d

shared int sf = 0xDEAD0011;    //068d
shared const int scf = 0xDEAD0012;   //068d
shared immutable int sif = 0xDEAD0013;   //068d

static int Sf = 0xDEAD0101;    //0678
static const int Scf = 0xDEAD0102;   //068d
static immutable int Sif = 0xDEAD0103;   //068d

static shared int Ssf = 0xDEAD0111;   //068d
static shared const int Sscf = 0xDEAD0112;  //068d
static shared immutable int Ssif = 0xDEAD0113;  //068d

int main()
{
  int f_ = 0xDEAD1001;     //073c**
  const int cf_ = 0xDEAD1002;    //073c*
  immutable int if_ = 0xDEAD1003;   //073c*

  shared int sf_ = 0xDEAD1011;    //073c**
  shared const int scf_ = 0xDEAD1012;   //073c*
  shared immutable int sif_ = 0xDEAD1013;  //073c*

  static int Sf_ = 0xDEAD1101;    //0678
  static const int Scf_ = 0xDEAD1102;   //068d
  static immutable int Sif_ = 0xDEAD1103;  //068d

  static shared int Ssf_ = 0xDEAD1111;   //068d
  static shared const int Sscf_ = 0xDEAD1112;  //068d
  static shared immutable int Ssif_ = 0xDEAD1113; //068d

  // prevent optimization
  return f+cf+_if+sf+scf+sif+Sf+Scf+Sif+Ssf+Sscf+Ssif+
    f_+cf_+if_+sf_+scf_+sif_+Sf_+Scf_+Sif_+Ssf_+Sscf_+Ssif_;
}

// The numbers in comments represent the sections as printed by dumpbin:
//0678  LED386 (TLS?)
//068d  LED386 (global)
//073c  CMD386 (code)
//* only appears in obj when compiled with -g
//** does not appear in obj when compiled with -O
May 14 2009
next sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
Lionello Lunesu wrote:
 I like shared/const/immutable as much as the next guy, but there are now 
 2x2x3=12 ways to decorate a variable. Furthermore, by either declaring 
 the variable globally or locally (stack), we end up with 24 possible 
 declaration. See the code at the end of this post.
The decision to make a variable a static class or module member is independent of whether to make it shared or not. Shared and const-level have to do with controlling access to the variable. An immutable variable does not need to be declared shared. Shared const is for publish-subscribe sort of deals. Shared mutable is for cooperative writing to the variable. The point of a shared local variable is to pass it to another thread or set of threads, which will then be able to mutate it without trouble.
May 14 2009
parent reply "Lionello Lunesu" <lionello lunesu.remove.com> writes:
"Christopher Wright" <dhasenan gmail.com> wrote in message 
news:gugs7b$70p$1 digitalmars.com...
 Lionello Lunesu wrote:
 I like shared/const/immutable as much as the next guy, but there are now 
 2x2x3=12 ways to decorate a variable. Furthermore, by either declaring 
 the variable globally or locally (stack), we end up with 24 possible 
 declaration. See the code at the end of this post.
The decision to make a variable a static class or module member is independent of whether to make it shared or not.
You're right, of course. I realize now that "static" is a storage class (when used locally) not a type modifier.
 Shared and const-level have to do with controlling access to the variable.

 An immutable variable does not need to be declared shared.
So, immutable implies shared.
 Shared const is for publish-subscribe sort of deals.
You mean one thread can change the value, but for another thread it's constant? I can see how it would be useful using reference types, but I don't understand how it would work with value types..
 Shared mutable is for cooperative writing to the variable.
This one I understood :)
 The point of a shared local variable is to pass it to another thread or 
 set of threads, which will then be able to mutate it without trouble.
As before, how can an int (value type) on the stack ever be shared with another thread? It would always have to be copied... Can you give me an example please? Thanks, L.
May 14 2009
next sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
Lionello Lunesu wrote:
 
 "Christopher Wright" <dhasenan gmail.com> wrote in message 
 news:gugs7b$70p$1 digitalmars.com...
 Lionello Lunesu wrote:
 I like shared/const/immutable as much as the next guy, but there are 
 now 2x2x3=12 ways to decorate a variable. Furthermore, by either 
 declaring the variable globally or locally (stack), we end up with 24 
 possible declaration. See the code at the end of this post.
The decision to make a variable a static class or module member is independent of whether to make it shared or not.
You're right, of course. I realize now that "static" is a storage class (when used locally) not a type modifier.
 Shared and const-level have to do with controlling access to the 
 variable.

 An immutable variable does not need to be declared shared.
So, immutable implies shared.
Immutable is threadsafe. Shared implies automatic locking, I believe; immutable variables do not need any locking.
 Shared const is for publish-subscribe sort of deals.
You mean one thread can change the value, but for another thread it's constant? I can see how it would be useful using reference types, but I don't understand how it would work with value types..
Shared const doesn't really work for value types; it ends up being the same as immutable. Unless you have a mutable pointer to the value, in which case you can write to the value through that pointer. That is not safe -- the compiler is free to see that this variable is const and a value type, which means you can't ever write to it, and then put it in read-only memory. Const that doesn't boil down to immutable works a fair bit better with object-oriented code. You wrap your value in a class, create a mutable instance, and send it to a bunch of other functions or objects or threads expecting a const object. They can't use the mutators, but they can use the accessors.
 Shared mutable is for cooperative writing to the variable.
This one I understood :)
 The point of a shared local variable is to pass it to another thread 
 or set of threads, which will then be able to mutate it without trouble.
As before, how can an int (value type) on the stack ever be shared with another thread? It would always have to be copied... Can you give me an example please?
By reference. int i; shared int* j = &i; sendToManyThreads(j);
May 14 2009
parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Christopher Wright wrote:
 Lionello Lunesu wrote:
 "Christopher Wright" <dhasenan gmail.com> wrote in message 
 news:gugs7b$70p$1 digitalmars.com...
 Lionello Lunesu wrote:
 I like shared/const/immutable as much as the next guy, but there are 
 now 2x2x3=12 ways to decorate a variable. Furthermore, by either 
 declaring the variable globally or locally (stack), we end up with 
 24 possible declaration. See the code at the end of this post.
The decision to make a variable a static class or module member is independent of whether to make it shared or not.
You're right, of course. I realize now that "static" is a storage class (when used locally) not a type modifier.
 Shared and const-level have to do with controlling access to the 
 variable.

 An immutable variable does not need to be declared shared.
So, immutable implies shared.
Immutable is threadsafe. Shared implies automatic locking, I believe; immutable variables do not need any locking.
So one has to wonder what code will be generated for "shared immutable".. an immutable with (useless) locking?
 Shared const is for publish-subscribe sort of deals.
You mean one thread can change the value, but for another thread it's constant? I can see how it would be useful using reference types, but I don't understand how it would work with value types..
Shared const doesn't really work for value types; it ends up being the same as immutable. Unless you have a mutable pointer to the value, in which case you can write to the value through that pointer. That is not safe -- the compiler is free to see that this variable is const and a value type, which means you can't ever write to it, and then put it in read-only memory. Const that doesn't boil down to immutable works a fair bit better with object-oriented code. You wrap your value in a class, create a mutable instance, and send it to a bunch of other functions or objects or threads expecting a const object. They can't use the mutators, but they can use the accessors.
Got it. Thanks.. L.
May 18 2009
parent Christopher Wright <dhasenan gmail.com> writes:
Lionello Lunesu wrote:
 So one has to wonder what code will be generated for "shared 
 immutable".. an immutable with (useless) locking?
If that happens, Walter will get a bug report, and he'll change it so that shared immutable variables are silently converted to non-shared immutable variables. That currently happens with incompatible type modifiers and storage classes, I believe.
May 18 2009
prev sibling next sibling parent BCS <none anon.com> writes:
Hello Lionello,

 "Christopher Wright" <dhasenan gmail.com> wrote in message

 The point of a shared local variable is to pass it to another thread
 or set of threads, which will then be able to mutate it without
 trouble.
 
As before, how can an int (value type) on the stack ever be shared with another thread? It would always have to be copied... Can you give me an example please?
// without lookin up the details of threading void main() { int i; with(new Thread({i++;})) { Start(); Wait(); } }
May 14 2009
prev sibling parent reply BCS <none anon.com> writes:
Hello Lionello,

 "Christopher Wright" <dhasenan gmail.com> wrote in message

 The point of a shared local variable is to pass it to another thread
 or set of threads, which will then be able to mutate it without
 trouble.
 
As before, how can an int (value type) on the stack ever be shared with another thread? It would always have to be copied... Can you give me an example please?
// without lookin up the details of threading void main() { int i; with(new Thread({i++;})) { Start(); Wait(); } }
May 14 2009
parent Lionello Lunesu <lio lunesu.remove.com> writes:
BCS wrote:
 Hello Lionello,
 
 "Christopher Wright" <dhasenan gmail.com> wrote in message

 The point of a shared local variable is to pass it to another thread
 or set of threads, which will then be able to mutate it without
 trouble.
As before, how can an int (value type) on the stack ever be shared with another thread? It would always have to be copied... Can you give me an example please?
// without lookin up the details of threading void main() { int i; with(new Thread({i++;})) { Start(); Wait(); } }
:O Indeed, that works! Which is scary, since the compiler did not detect the access to 'i' from another thread. In this case the code is safe, but only because of the Wait/join at the end.. This looks like a hole in the shared/tls system and there's nothing the compiler can do about it. :( L.
May 18 2009
prev sibling parent BCS <none anon.com> writes:
Hello Lionello,

 
 //The code:
 
immutable need not be shared
 shared immutable int sif = 0xDEAD0013;   //068d
static global is redundent
 static int Sf = 0xDEAD0101;    //0678
 static const int Scf = 0xDEAD0102;   //068d
 static immutable int Sif = 0xDEAD0103;   //068d
 static shared int Ssf = 0xDEAD0111;   //068d 
 static shared const int Sscf = 0xDEAD0112;  //068d 
 static shared immutable int Ssif = 0xDEAD0113;  //068d
 int main()
 {
I'm not shure what this would be used for
 shared const int scf_ = 0xDEAD1012;   //073c*
immutable need not be shared
 shared immutable int sif_ = 0xDEAD1013;  //073c*
I'm not shure what this would be used for
 static const int Scf_ = 0xDEAD1102;   //068d
I think this is redundent
 static immutable int Sif_ = 0xDEAD1103;  //068d
I'm not shure what this would be used for
 static shared const int Sscf_ = 0xDEAD1112;  //068d
immutable need not be shared
 static shared immutable int Ssif_ = 0xDEAD1113; //068d
By my count 13 of the 24 cases are never needed in paractace as they end up redundent. FWIW, I like the current setup.
May 14 2009