Static constructor

Steven Schveighoffer schveiguy at gmail.com
Fri Jan 15 16:24:57 UTC 2021


On 1/6/21 12:05 PM, ludo wrote:
> I read in the documentation
> "Static constructors are used to initialize static class members with 
> values that cannot be computed at compile time"
> 
> I try to understand the design of the following code:
> 
> ---
> class OpenAL
> {
>      static string[int] ALErrorLookup;
>      static Object mutex;
> 
>      // Initialize static variables
>      static this ()
>      {    ALErrorLookup = [
>              0xA001: "AL_INVALID_NAME"[],
>              0xA002: "AL_ILLEGAL_ENUM",
>              0xA002: "AL_INVALID_ENUM",
>              0xA003: "AL_INVALID_VALUE",
>              0xA004: "AL_ILLEGAL_COMMAND",
>              0xA004: "AL_INVALID_OPERATION",
>              0xA005: "AL_OUT_OF_MEMORY"
>          ];
>          mutex = new Object();
>      }
> 
>         static anotherfunc()
>         {}
> 
>      static Object getMutex()
>      {    return mutex;
>          }
> }
> ---
> 
> At this point, I have not looked up Object, guess must be a class. It 
> seems to me that ALErrorLookup can be computed at compile time... So the 
> constructor is static because mutex "can not be computed at compiled time"?

Associative arrays can be computed at compile time, and used at compile 
time. BUT they cannot be transferred to runtime AAs (yet).

So likely that is the reason the AA initialization is in there.

You can (now) create classes at compile-time, and then assign them to 
variables as static initializers. I don't know if that means you can 
create the mutex at compile-time. I know OS mutex primitives can be 
initialized at compile time. I don't know if that works properly here.

Also note that what is happening here is not correct in D2 (I see that 
it's D1 you noted in a subsequent message), as `static this()` is run 
once per thread (and mutex is going to get one instance per thread). So 
most likely you need to change both of these to shared.

> 
> The idea of the dev (from context) is to that this class will just be a 
> wrapper, no instance necessary. So anotherfunc(), which does the main 
> work, is static and everything goes this way.
> 
> Then getMutex returns the static mutex when necessary... Have not looked 
> that up yet either.

It doesn't make a whole lot of sense, since mutex is publicly accessible.

> But, I don't know, i have a feeling that this is over complicated. For 
> example, can't we have AlErrorlook-up initialized another way in D, a 
> static mutex in the getMutex function directly (with if (mutex == null) 
> {mutex = new Object()} .

No on the AA (as noted above). The mutex *is* created on demand. Every 
Object can have a mutex, and it's only created when you synchronize it 
for the first time.

> I don't know, is it the proper D way? And also, when we have those 
> classes with everything static, does it even make sense to have a class? 
> This module actually contains only this class 
> (https://tinyurl.com/yxt2xw23) Shouldn't we have one module with normal 
> functions?
> 
> ANY input is learning material for me. Thanks.

I would say the AA initialization is standard D. Using the class as a 
namespace isn't standard or necessary. If anything, it should be a 
struct, or you can use a template. But I can't see why you can't just 
use a module.

-Steve


More information about the Digitalmars-d-learn mailing list