www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Only const or immutable class thread local variables are allowed

reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
Hello all,

I have a challenge, which is this: I'd like to have a public property which
will 
return a reference to an internally stored class instance.

     ref MyClass myProperty()  property
     {
         ...
     }

However, this runs into a problem: I can't use "static" to internally store a 
class instance.

I worked out a cheaty way to get around this which goes like this:

     ref MyClass myProperty()  property
     {
         struct MyCheat
         {
             MyClass whatIReallyWant = new MyClass;
         }

         static MyCheat cheat;
         // ... do other stuff ...
         return cheat.whatIReallyWant;
     }

... but I'm wondering if anyone has any alternative suggestions (or warnings or 
caveats about the cheaty method).

Thanks & best wishes,

     -- Joe
Dec 08 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/08/2013 10:00 AM, Joseph Rushton Wakeling wrote:

 I have a challenge, which is this: I'd like to have a public property
 which will return a reference to an internally stored class instance.

      ref MyClass myProperty()  property
      {
          ...
      }
First, the usual question: Since class varibles are already references, do you really need to return ref? In any case, I think class static this is the solution: class MyClass { static MyClass whatIReallyWant; static this() { whatIReallyWant = new MyClass; } /* ref */ MyClass myProperty() property { return whatIReallyWant; } } void main() { auto m = new MyClass; auto s = m.myProperty; } Ali
Dec 08 2013
parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 08/12/13 21:12, Ali Çehreli wrote:
 In any case, I think class static this is the solution:
I think I may have misled you by talking about properties, because I _don't_ mean a property of a class. I mean a public standalone function that is marked as a property, which returns a persistent instance of some class. The actual motivation is reimplementing std.random.rndGen but with class-based RNGs instead of structs :-) A consequence of this is that I don't think a static class instance can work, because the returned class has to be non-const -- it's an RNG that will be updated!
Dec 08 2013
parent reply "qznc" <qznc web.de> writes:
On Sunday, 8 December 2013 at 21:32:35 UTC, Joseph Rushton 
Wakeling wrote:
 On 08/12/13 21:12, Ali Çehreli wrote:
 In any case, I think class static this is the solution:
I think I may have misled you by talking about properties, because I _don't_ mean a property of a class. I mean a public standalone function that is marked as a property, which returns a persistent instance of some class. The actual motivation is reimplementing std.random.rndGen but with class-based RNGs instead of structs :-) A consequence of this is that I don't think a static class instance can work, because the returned class has to be non-const -- it's an RNG that will be updated!
I understand you are talking about the "Singleton" design pattern. You might want to look how std.parallelism does it with the default global thread pool. https://github.com/D-Programming-Language/phobos/blob/master/std/parallelism.d#L3261
Dec 08 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/08/2013 02:40 PM, qznc wrote:

 I understand you are talking about the "Singleton" design pattern.
 You might want to look how std.parallelism does it with the default
 global thread pool.

 https://github.com/D-Programming-Language/phobos/blob/master/std/parallelism.d#L3261
David Simcha presented it as a D-specific pattern and explained how D avoids at least one of the bugs of double-checked locking: http://www.youtube.com/watch?feature=player_detailpage&v=yMNMV9JlkcQ#t=1676 Ali
Dec 08 2013
next sibling parent reply "Joseph Rushton Wakeling" <joseph.wakeling webdrake.net> writes:
On Monday, 9 December 2013 at 00:24:44 UTC, Ali Çehreli wrote:
 David Simcha presented it as a D-specific pattern and explained 
 how D avoids at least one of the bugs of double-checked locking:


 http://www.youtube.com/watch?feature=player_detailpage&v=yMNMV9JlkcQ#t=1676
I will look at this in detail but instinctively based on what I understand a singleton to be for, I'm not sure it's what I want: I'm not looking for something truly global, only thread-global. Just so you can see, this is what I've got: https://github.com/WebDrake/std.random2/blob/master/std/random2/generator.d#L18 https://github.com/WebDrake/std.random2/blob/master/std/random2/generator.d#L688 ... and this is what it's designed to replace: https://github.com/D-Programming-Language/phobos/blob/master/std/random.d#L1148 https://github.com/D-Programming-Language/phobos/blob/master/std/random.d#L1104
Dec 08 2013
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, December 09, 2013 06:19:19 Joseph Rushton Wakeling wrote:
 On Monday, 9 December 2013 at 00:24:44 UTC, Ali Çehreli wrote:
 David Simcha presented it as a D-specific pattern and explained
 how D avoids at least one of the bugs of double-checked locking:
 
 
 http://www.youtube.com/watch?feature=player_detailpage&v=yMNMV9JlkcQ#t=167
 6
I will look at this in detail but instinctively based on what I understand a singleton to be for, I'm not sure it's what I want: I'm not looking for something truly global, only thread-global.
It's still essentially a singleton - it's just that it's a single instance per thread in that case instead of per program. And you avoid all of the threading-related initialization issues with singletons if it's thread-local. Just check whether it's null, initialize it if it is (leave it alone if it isn't), and then do whatever you're going to do with it. - Jonathan M Davis
Dec 09 2013
prev sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 10/12/13 06:33, Jonathan M Davis wrote:
 It's still essentially a singleton - it's just that it's a single instance per
 thread in that case instead of per program. And you avoid all of the
 threading-related initialization issues with singletons if it's thread-local.
 Just check whether it's null, initialize it if it is (leave it alone if it
 isn't), and then do whatever you're going to do with it.
So for example the below code as an rndGen where Random is a class, not a struct? I think I was misled by the "Only const or immutable ..." part of the error message: I'd assumed that any class that actually modified its internal state would be disallowed as a static instance. /////////////////////////////////////////////////////////////////////////////// ref Random rndGen() property { static Random result = null; if (result is null) { result = new Random; static if (isSeedable!(Random, typeof(repeat(0).map!((a) => unpredictableSeed)))) { result.seed(repeat(0).map!((a) => unpredictableSeed)); } else { result.seed(unpredictableSeed); } } return result; } ///////////////////////////////////////////////////////////////////////////////
Dec 09 2013
prev sibling parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 09/12/13 01:24, Ali Çehreli wrote:
 On 12/08/2013 02:40 PM, qznc wrote:

 I understand you are talking about the "Singleton" design pattern.
 You might want to look how std.parallelism does it with the default
 global thread pool.

 https://github.com/D-Programming-Language/phobos/blob/master/std/parallelism.d#L3261
David Simcha presented it as a D-specific pattern and explained how D avoids at least one of the bugs of double-checked locking:
(i) That's very cool :-D (ii) I still think it's not what I want. The "static" class instance doesn't need to be globally global, I want the default thread-local storage as per the existing std.random.rndGen. Hence the solution I arrived at, but which I'm sure could be improved.
Dec 08 2013
parent "qznc" <qznc web.de> writes:
On Monday, 9 December 2013 at 06:43:05 UTC, Joseph Rushton 
Wakeling wrote:
 On 09/12/13 01:24, Ali Çehreli wrote:
 On 12/08/2013 02:40 PM, qznc wrote:

 I understand you are talking about the "Singleton" design 
 pattern.
 You might want to look how std.parallelism does it with the 
 default
 global thread pool.

 https://github.com/D-Programming-Language/phobos/blob/master/std/parallelism.d#L3261
(ii) I still think it's not what I want. The "static" class instance doesn't need to be globally global, I want the default thread-local storage as per the existing std.random.rndGen. Hence the solution I arrived at, but which I'm sure could be improved.
class Foo { private static Foo singleton = null; property public static Foo global() { if (singleton is null) singleton = new Foo(); return singleton; } } Running example: http://www.dpaste.dzfl.pl/f65513fa
Dec 09 2013
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, December 10, 2013 08:41:25 Joseph Rushton Wakeling wrote:
 On 10/12/13 06:33, Jonathan M Davis wrote:
 It's still essentially a singleton - it's just that it's a single instance
 per thread in that case instead of per program. And you avoid all of the
 threading-related initialization issues with singletons if it's
 thread-local. Just check whether it's null, initialize it if it is (leave
 it alone if it isn't), and then do whatever you're going to do with it.
So for example the below code as an rndGen where Random is a class, not a struct?
Yeah. Something like that.
 I think I was misled by the "Only const or immutable ..." part of the error
 message: I'd assumed that any class that actually modified its internal
 state would be disallowed as a static instance.
It's a matter of what you can directly initialize a non-local variable with. Module-level variables, static variables, and member variables all have to be known at compile time, and you can't have a mutable class instance being constructed at compile time and then kept around until runtime. - Jonathan M Davis
Dec 09 2013
prev sibling next sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 10/12/13 08:44, Jonathan M Davis wrote:
 Yeah. Something like that.
What I like is that it actually comes out slightly nicer than the existing code -- you don't need an extra static boolean to check if the RNG has been initialized. This experience is proving typical of class-based RNG and RNG-dependent code so far.
 I think I was misled by the "Only const or immutable ..." part of the error
 message: I'd assumed that any class that actually modified its internal
 state would be disallowed as a static instance.
It's a matter of what you can directly initialize a non-local variable with. Module-level variables, static variables, and member variables all have to be known at compile time, and you can't have a mutable class instance being constructed at compile time and then kept around until runtime.
That's obvious in retrospect but not on the basis of the error message: Error: variable std.random2.generator.rndGen.result is mutable. Only const or immutable class thread local variable are allowed, not std.random2.generator.MersenneTwisterEngine!(uint, 32, 624, 397, 31, 2567483615u, 11, 4294967295u, 7, 2636928640u, 15, 4022730752u, 18, 1812433253u).MersenneTwisterEngine Would this be better? Cannot initialize thread-local class variable %s with a mutable value. Only const or immutable initial values are allowed (e.g. null).
Dec 10 2013
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, December 10, 2013 09:13:12 Joseph Rushton Wakeling wrote:
 On 10/12/13 08:44, Jonathan M Davis wrote:
 It's a matter of what you can directly initialize a non-local variable
 with. Module-level variables, static variables, and member variables all
 have to be known at compile time, and you can't have a mutable class
 instance being constructed at compile time and then kept around until
 runtime.
That's obvious in retrospect but not on the basis of the error message: Error: variable std.random2.generator.rndGen.result is mutable. Only const or immutable class thread local variable are allowed, not std.random2.generator.MersenneTwisterEngine!(uint, 32, 624, 397, 31, 2567483615u, 11, 4294967295u, 7, 2636928640u, 15, 4022730752u, 18, 1812433253u).MersenneTwisterEngine
A lot of dmd's error messages aren't great.
 Would this be better?
 
      Cannot initialize thread-local class variable %s with a mutable value. 
 Only const or immutable initial values are allowed (e.g. null).
That would be better. - Jonathan M Davis
Dec 10 2013
prev sibling parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 10/12/13 09:27, Jonathan M Davis wrote:
 A lot of dmd's error messages aren't great.

 Would this be better?

       Cannot initialize thread-local class variable %s with a mutable value.
 Only const or immutable initial values are allowed (e.g. null).
That would be better.
https://github.com/D-Programming-Language/dmd/pull/2943 I can also add a bugzilla issue if you like, but maybe seems overkill ... ?
Dec 10 2013
next sibling parent reply "qznc" <qznc web.de> writes:
On Tuesday, 10 December 2013 at 09:50:56 UTC, Joseph Rushton 
Wakeling wrote:
 On 10/12/13 09:27, Jonathan M Davis wrote:
 A lot of dmd's error messages aren't great.

 Would this be better?

      Cannot initialize thread-local class variable %s with a 
 mutable value.
 Only const or immutable initial values are allowed (e.g. 
 null).
That would be better.
https://github.com/D-Programming-Language/dmd/pull/2943 I can also add a bugzilla issue if you like, but maybe seems overkill ... ?
The changelog is partially generated from Bugzilla issues. That was the main reason to also add issues for pull request, afaik.
Dec 10 2013
parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 10/12/13 11:31, qznc wrote:
 The changelog is partially generated from Bugzilla issues. That was the main
 reason to also add issues for pull request, afaik.
Fair enough :-) https://d.puremagic.com/issues/show_bug.cgi?id=11714
Dec 10 2013
prev sibling parent "qznc" <qznc web.de> writes:
On Tuesday, 10 December 2013 at 09:50:56 UTC, Joseph Rushton
Wakeling wrote:
 On 10/12/13 09:27, Jonathan M Davis wrote:
 A lot of dmd's error messages aren't great.

 Would this be better?

      Cannot initialize thread-local class variable %s with a 
 mutable value.
 Only const or immutable initial values are allowed (e.g. 
 null).
That would be better.
https://github.com/D-Programming-Language/dmd/pull/2943 I can also add a bugzilla issue if you like, but maybe seems overkill ... ?
The changelog is partially generated from Bugzilla issues. That was the main reason to also add issues for pull request, afaik.
Dec 10 2013