Re: Static constructors in circularly imported modules - again

2010-05-29 Thread Eldar Insafutdinov
Max Samukha Wrote:

 On 27.05.2010 13:37, Max Samukha wrote:
  There was a discussion about those a while ago that terminated with
  Andrei's authoritative it would be a step backward.
 
  I am not entirely convinced that there had been a step forward in the
  first place. Defining static construction order to be determined by the
  module import graph had been a half step forward. Completely disallowing
  static construction of circularly imported modules - a half step
  backward. The result is std.stdiobase and impossibility to initialize
  static data in mixins without resorting to lazy initialization.
 
  I can live with hacks like std.stdiobase when such are possible. What is
  more critical is initialization of mixins. Restating the problem:
 
  module a;
  mixin template Foo()
  {
  static immutable Object foo;
  shared static this()
  {
  foo = cast(immutable)new Object;
  }
  }
 
  
  module b;
  import a;
  import c;
 
  mixin Foo;
 
  
  module c;
  import a;
  import b;
 
  mixin Foo;
 
  In this scenario one is forced to avoid static constructors by lazily
  initializing foo and using some kind of synchronization, which should be
  absolutely unnecessary and sometimes is not tolerable.
 
  So which of the following is going to happen?
 
  1. The current blinkered design will stay.
  2. A solution will be provided before D2 is feature-freezed.
 
 Feature-frozen. Sorry.
 
 
  Note that I am well aware of
  http://yosefk.com/c++fqa/ctors.html#fqa-10.12 etc, but simply
  disallowing static construction is not a good solution for static
  construction problems.
 
 I'd really appreciate a reply from the language designers. What are the 
 plans?
 
 1. Static constructor semantics won't change.
 2. We've worked out a solution and it will be implemented in a future 
 compiler release.
 
 Please care to type 1 or 2. Thank you!

Why has it become a tradition to ignore uncomfortable questions in these 
newsgroups?


Re: Static constructors in circularly imported modules - again

2010-05-28 Thread Max Samukha

On 27.05.2010 13:37, Max Samukha wrote:

There was a discussion about those a while ago that terminated with
Andrei's authoritative it would be a step backward.

I am not entirely convinced that there had been a step forward in the
first place. Defining static construction order to be determined by the
module import graph had been a half step forward. Completely disallowing
static construction of circularly imported modules - a half step
backward. The result is std.stdiobase and impossibility to initialize
static data in mixins without resorting to lazy initialization.

I can live with hacks like std.stdiobase when such are possible. What is
more critical is initialization of mixins. Restating the problem:

module a;
mixin template Foo()
{
static immutable Object foo;
shared static this()
{
foo = cast(immutable)new Object;
}
}


module b;
import a;
import c;

mixin Foo;


module c;
import a;
import b;

mixin Foo;

In this scenario one is forced to avoid static constructors by lazily
initializing foo and using some kind of synchronization, which should be
absolutely unnecessary and sometimes is not tolerable.

So which of the following is going to happen?

1. The current blinkered design will stay.
2. A solution will be provided before D2 is feature-freezed.


Feature-frozen. Sorry.



Note that I am well aware of
http://yosefk.com/c++fqa/ctors.html#fqa-10.12 etc, but simply
disallowing static construction is not a good solution for static
construction problems.


I'd really appreciate a reply from the language designers. What are the 
plans?


1. Static constructor semantics won't change.
2. We've worked out a solution and it will be implemented in a future 
compiler release.


Please care to type 1 or 2. Thank you!


Static constructors in circularly imported modules - again

2010-05-27 Thread Max Samukha
There was a discussion about those a while ago that terminated with 
Andrei's authoritative it would be a step backward.


I am not entirely convinced that there had been a step forward in the 
first place. Defining static construction order to be determined by the 
module import graph had been a half step forward. Completely disallowing 
static construction of circularly imported modules - a half step 
backward. The result is std.stdiobase and impossibility to initialize 
static data in mixins without resorting to lazy initialization.


I can live with hacks like std.stdiobase when such are possible. What is 
more critical is initialization of mixins. Restating the problem:


module a;
mixin template Foo()
{
   static immutable Object foo;
   shared static this()
   {
   foo = cast(immutable)new Object;
   }
}


module b;
import a;
import c;

mixin Foo;


module c;
import a;
import b;

mixin Foo;

In this scenario one is forced to avoid static constructors by lazily 
initializing foo and using some kind of synchronization, which should be 
absolutely unnecessary and sometimes is not tolerable.


So which of the following is going to happen?

1. The current blinkered design will stay.
2. A solution will be provided before D2 is feature-freezed.

Note that I am well aware of 
http://yosefk.com/c++fqa/ctors.html#fqa-10.12 etc, but simply 
disallowing static construction is not a good solution for static 
construction problems.


Re: Static constructors in circularly imported modules - again

2010-05-27 Thread Max Samukha

On 05/27/2010 01:37 PM, Max Samukha wrote:



module a;
mixin template Foo()
{
static immutable Object foo;
shared static this()
{
foo = cast(immutable)new Object;
}
}


module b;
import a;
import c;

mixin Foo;


module c;
import a;
import b;

mixin Foo;

In this scenario one is forced to avoid static constructors by lazily
initializing foo and using some kind of synchronization, which should be
absolutely unnecessary and sometimes is not tolerable.



Ok, I've just thought of a way to avoid synchronization (using __gshared 
for simplicity):


module a;
mixin template Foo()
{
static __gshared Object foo; // shared foo
static Object tlFoo; // thread-local foo

Object getFoo()
{
if (!tlFoo)
{
synchronized(lock)
{
if (!foo)
foo = new Object;
}
tlFoo = foo;
}
return tlFoo;
}
}

There is still unnecessary overhead of accessing and testing the 
thread-local variable.





Re: Static constructors in circularly imported modules - again

2010-05-27 Thread Jason House
Max Samukha Wrote:

 There was a discussion about those a while ago that terminated with 
 Andrei's authoritative it would be a step backward.
 
 I am not entirely convinced that there had been a step forward in the 
 first place. Defining static construction order to be determined by the 
 module import graph had been a half step forward. Completely disallowing 
 static construction of circularly imported modules - a half step 
 backward. The result is std.stdiobase and impossibility to initialize 
 static data in mixins without resorting to lazy initialization.
 
 I can live with hacks like std.stdiobase when such are possible. What is 
 more critical is initialization of mixins. Restating the problem:
 
 module a;
 mixin template Foo()
 {
 static immutable Object foo;
 shared static this()
 {
 foo = cast(immutable)new Object;
 }
 }
 
 
 module b;
 import a;
 import c;
 
 mixin Foo;
 
 
 module c;
 import a;
 import b;
 
 mixin Foo;
 
 In this scenario one is forced to avoid static constructors by lazily 
 initializing foo and using some kind of synchronization, which should be 
 absolutely unnecessary and sometimes is not tolerable.
 
 So which of the following is going to happen?
 
 1. The current blinkered design will stay.
 2. A solution will be provided before D2 is feature-freezed.
 
 Note that I am well aware of 
 http://yosefk.com/c++fqa/ctors.html#fqa-10.12 etc, but simply 
 disallowing static construction is not a good solution for static 
 construction problems.

In module b, delete the import of c. In module c, delete the import of b. Your 
sample code will then  compile and run. It probably wouldn't do what you want 
though; you'll have two globals (b.foo and c.foo).  I suspect what you really 
want is one global a.foo?


Re: Static constructors in circularly imported modules - again

2010-05-27 Thread Max Samukha

On 05/27/2010 03:47 PM, Jason House wrote:


In module b, delete the import of c. In module c, delete the import of b. Your sample code will then  compile and run.  It probably wouldn't do what you want though; you'll have two globals 

(b.foo and c.foo).  I suspect what you really want is one global a.foo?

Two distinct globals. There is a more concrete example:

module QObject;

class QMetaObject
{
...
}

mixin template Q_OBJECT()
{
...

immutable(QMetaObject) metaObject() immutable
{
return staticMetaObject;
}

static immutable QMetaObject staticMetaObject;
shared static this()
{
staticMetaObject = 
cast(immutable)QMetaObject.create!(typeof(this));

}
}


module a;
import QObject;
import b;

class A : QObject
{
B b;
mixin Q_OBJECT;
}


module b;
import QObject;
import a;

class B :
{
A a;
mixin Q_OBJECT;
}

When mixed in a class, Q_OBJECT, among other things, associates a global 
RTTI object with that class. Ideally, this object should be created at 
program startup.


We cannot impose on the user of Q_OBJECT the requirement that a and b 
should not be circularly imported or that he has to manually call an 
initialization function etc.


Re: Static constructors in circularly imported modules - again

2010-05-27 Thread Michel Fortin

On 2010-05-27 09:57:30 -0400, Max Samukha spam...@d-coding.com said:

We cannot impose on the user of Q_OBJECT the requirement that a and b 
should not be circularly imported or that he has to manually call an 
initialization function etc.


Just a small note...

In the D/Objective-C bridge, I've resorted to lazy initialization for 
this kind of thing. This way there is no module constructors and 
circular imports work as expected. But it isn't thread-safe, and I 
expect it would be a pain to make lazy initialization thread-safe, 
although I haven't tried yet.



--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/



Re: Static constructors in circularly imported modules - again

2010-05-27 Thread Max Samukha

On 27.05.2010 18:38, Michel Fortin wrote:

But it isn't thread-safe, and I
expect it would be a pain to make lazy initialization thread-safe,
although I haven't tried yet.


That has been the very point of this thread (no pun). In my other post I 
supplied a hack that uses two variables, shared and TLS, to reduce the 
cost of accessing the global. Not ideal at all but at least it requires 
synchronization only during the first access.