www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - D2 __gshared and compatibility with D1

reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
Hello,

As some of you might know, there is a great package for D called 
Derelict (Derelict2 now actually). It provides bindings for several 
interesting C libraries like SDL, OpenGL and FreeType. The key point of 
Derelict is that it is designed to work exclusively with dynamic 
libraries. To achieve this, it provides a bunch of function pointers for 
  every library, and these pointers are bound to function addresses when 
dynamic library is actually loaded. Simple example:

extern(C) void function() someLibFunction;

//...
void main()
{
    DerelictSomeLib.load(); // this call will load dynamic library and 
initialize someLibFunction

    someLibFunction();

}

Another key point of Derelict is compatibility with both D1 and D2. But 
for current D2, someLibFunction will be initialized only for the thread 
that called DerelictSomeLib.load(), because the pointer itself is 
thread-local, thus all other threads will also need to call 
DerelictSomeLib.load(), which looks like a gap in compatibility. So 
basically it would require to enclose function pointers  in __gshared 
block, and here comes the problem: there is no __gshared in D1, so 
mixins should be used to keep compatibility.

I proposed a solution which is based on 'templating' function pointers, 
that is, putting them into a parameterless template, and then mixing 
this template in like this:

// for simplicity, no further version checking provided, but for
// dmd we would also need to check compiler version here
version (D_Version2)
{
     mixin("__gshared { mixin FunctionPointers; }");
}
else
{
     mixin FunctionPointers;
}

It works fine, but author and maintainer of Derelict is somewhat 
skeptical about templates (and thus he's against applying this 
solution), and actually I agree with him that this approach has a 
significant impact on compile times, especially for libraries with lots 
of functions like OpenGL.

Is there some other way of __gshared'ing a set of data without breaking 
compatibility with D1? Current D2 syntax allows __gshared import, but it 
  has no effect on imported module (and I don't think it should, seems 
more like an inconsistency to me).
Jan 24 2010
parent reply Mike Wey <mike-wey example.com> writes:
On 01/24/2010 05:13 PM, Stanislav Blinov wrote:
 Hello,

 As some of you might know, there is a great package for D called
 Derelict (Derelict2 now actually). It provides bindings for several
 interesting C libraries like SDL, OpenGL and FreeType. The key point of
 Derelict is that it is designed to work exclusively with dynamic
 libraries. To achieve this, it provides a bunch of function pointers for
 every library, and these pointers are bound to function addresses when
 dynamic library is actually loaded. Simple example:

 extern(C) void function() someLibFunction;

 //...
 void main()
 {
 DerelictSomeLib.load(); // this call will load dynamic library and
 initialize someLibFunction

 someLibFunction();

 }

 Another key point of Derelict is compatibility with both D1 and D2. But
 for current D2, someLibFunction will be initialized only for the thread
 that called DerelictSomeLib.load(), because the pointer itself is
 thread-local, thus all other threads will also need to call
 DerelictSomeLib.load(), which looks like a gap in compatibility. So
 basically it would require to enclose function pointers in __gshared
 block, and here comes the problem: there is no __gshared in D1, so
 mixins should be used to keep compatibility.

 I proposed a solution which is based on 'templating' function pointers,
 that is, putting them into a parameterless template, and then mixing
 this template in like this:

 // for simplicity, no further version checking provided, but for
 // dmd we would also need to check compiler version here
 version (D_Version2)
 {
 mixin("__gshared { mixin FunctionPointers; }");
 }
 else
 {
 mixin FunctionPointers;
 }

 It works fine, but author and maintainer of Derelict is somewhat
 skeptical about templates (and thus he's against applying this
 solution), and actually I agree with him that this approach has a
 significant impact on compile times, especially for libraries with lots
 of functions like OpenGL.

 Is there some other way of __gshared'ing a set of data without breaking
 compatibility with D1? Current D2 syntax allows __gshared import, but it
 has no effect on imported module (and I don't think it should, seems
 more like an inconsistency to me).

With GtkD we define a function that returns an empty string or one containing __gshared depending on the dmd version, and then mixes that in with the function pointers, like so: version(D_Version2) { string gshared() { return "__gshared "; } } else { char[] gshared() { return ""; } } mixin( gshared ~ "large string containing the function pointers" ); It does increase the compile time a little. -- Mike Wey
Jan 24 2010
parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
Mike Wey wrote:
 With GtkD we define a function that returns an empty string or one 
 containing __gshared depending on the dmd version, and then mixes that 
 in with the function pointers

Thank you, that is an interesting option.
Jan 25 2010