Re: Static constructor

2021-01-18 Thread ludo via Digitalmars-d-learn
The mutex isn't more "global", it's more "local" (although, 
this will make it shared).


Yes shared, this is what I meant by global :) Thanks, it's 
clearer now.




Re: Static constructor

2021-01-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/17/21 6:54 PM, ludo wrote:
Yes alright. I think the dev made a design mistake because he called 
synchronized( OpenAL.mutex ) when it should be more of a global, non 
OpenAL specific, mutex. I mean in the code there were things like  
(pseudo-code)

---
System {
   private int[] buffer

   func() {
     synch (openal.mutex)
     {
   openal.dosmthg (buffer)
   buffer.change() // buffer being the member of System
   openal.dosmthg(buffer)
     }
   }
}
---
Basically, it's the entire buffers handling ( the 3 statements) which 
should be done the "atomic" way, not just the calls to openAL. So the 
mutex should be a member variable of System at worse. I just replaced

synchronized ( openal.mutex )  {
by
synchronized { // create a global mutex

Of course synchronized (open.mutex) would probably work, but getting the 
mutex of an abstract class which is used only in part of the calls looks 
like a design error to me!


Not sure if this is right. If the mutex should be protecting *more* then 
you should move the scope of the mutex out of the object into module 
space (and make it shared so it actually is used across threads).


Your code there allocates a mutex for that specific block, and nothing 
else. The mutex isn't more "global", it's more "local" (although, this 
will make it shared).


I'd follow some rules like:
1. If the mutex is for one specific block and does not need to be locked 
for any other code, then use a naked synchronized command. This is an 
odd case, because it is for a specific block of code, but works across 
all calls of that code. So the data it protects needs to be only used in 
that code, but also used across all instances of the objects. I'd use 
this one rarely.
2. If the mutex is for data in a specific object, make it a member of 
that object (or use the object itself as the mutex).
3. If the mutex is for static data in an object that is shared between 
threads, make it a shared static member of that object.
4. If the mutex is for static data in multiple objects, then put it in 
the module as a shared data item.


-Steve


Re: Static constructor

2021-01-17 Thread ludo via Digitalmars-d-learn

Thanks, as explained I am indeed porting old code.

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.


Yes alright. I think the dev made a design mistake because he 
called synchronized( OpenAL.mutex ) when it should be more of a 
global, non OpenAL specific, mutex. I mean in the code there were 
things like  (pseudo-code)

---
System {
  private int[] buffer

  func() {
synch (openal.mutex)
{
  openal.dosmthg (buffer)
  buffer.change() // buffer being the member of System
  openal.dosmthg(buffer)
}
  }
}
---
Basically, it's the entire buffers handling ( the 3 statements) 
which should be done the "atomic" way, not just the calls to 
openAL. So the mutex should be a member variable of System at 
worse. I just replaced

synchronized ( openal.mutex )  {
by
synchronized { // create a global mutex

Of course synchronized (open.mutex) would probably work, but 
getting the mutex of an abstract class which is used only in part 
of the calls looks like a design error to me!




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.


I replaced the AA entirely (by a switch in a nested function!). 
Got rid of the static init() then.


I replaced 'class' by 'struct', which does not oblige me to 
change the entire code using the syntax "OpenAL.smthg" . But I 
was tempted to go to the next step:
import OpenAL = ...openal; // should not have to change any code 
either if it works!


I just have to verify all the imports in the other modules and I 
can delete the "struct OpenAL" scope. I don't have enough 
experience in D2 to think about the impact of such a change 
though, ie from *

---
// openal.d file
module a.b.OpenAL

struct OpenAL{ void dosmthg()}

// another file
import a.b.OpenAL

OpenAL.dosmthg()
---

 to ***
---
// openal.d file
module a.b.OpenAL

void dosmthg()

// another file
import OpenAL = a.b.OpenAL

OpenAL.dosmthg()
---

Thanks again for all the info so far. Learning a lot.


Re: Static constructor

2021-01-15 Thread Steven Schveighoffer via Digitalmars-d-learn

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


Re: Static constructor

2021-01-15 Thread Imperatorn via Digitalmars-d-learn

On Friday, 15 January 2021 at 16:04:02 UTC, ludo wrote:
I believe so. I've never used OpenAL so it may have additional 
restrictions with multithreading, but from a simple "This 
function is only ever executed on one thread at a time", your 
above suggestions should work.


Apologies for the late reply.


No worry and thank you. I found the low-lock pattern on my own, 
digging more info. Smart pattern!
I put the synchronized function in front of the function. The 
problem with multithreading, is the difficulty to verify that 
it works fine :) But now the topic streams away from static 
constructor :) Cheers


Isn't that kind of the de facto standard? Well, saw this was 7 
years ago now 


Re: Static constructor

2021-01-15 Thread ludo via Digitalmars-d-learn
I believe so. I've never used OpenAL so it may have additional 
restrictions with multithreading, but from a simple "This 
function is only ever executed on one thread at a time", your 
above suggestions should work.


Apologies for the late reply.


No worry and thank you. I found the low-lock pattern on my own, 
digging more info. Smart pattern!
I put the synchronized function in front of the function. The 
problem with multithreading, is the difficulty to verify that it 
works fine :) But now the topic streams away from static 
constructor :) Cheers


Re: Static constructor

2021-01-14 Thread SealabJaster via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 11:28:12 UTC, ludo wrote:
Ok, I agree that ends up being a kind of strange singleton. But 
yes it was D v1 code. Do we agree that the following 
multi-threaded singleton pattern is the proper way as of today.


It looks fine to me. The D wiki has the following example which 
prevents the need for entering the synchronized block more than 
once per thread: https://wiki.dlang.org/Low-Lock_Singleton_Pattern


I should note that the example doesn't specify the value as 
shared, which technically isn't the correct thing to do, but 
`shared` itself can be a bit of an annoyance. However, you do 
need to ensure that your static variable is either shared or 
__gshared, otherwise it becomes thread-local.


If I understand, as of today an AA init depends on a runtime 
function for historical reasons. A bit weird for an array 
indeed perfectly known at compile time, but someday some  core 
language contributor will have a look at it, I guess.


Maybe in 5 years' time we'll get an uneventful discussion on it 
where it'd take 2 years to come to a conclusion before another 
year for it to actually be implemented.


If I understand well, this will accomplish the goal quoted with 
no further comestics needed! Only one keyword over explicitely 
using object mutex. Am I right?


I believe so. I've never used OpenAL so it may have additional 
restrictions with multithreading, but from a simple "This 
function is only ever executed on one thread at a time", your 
above suggestions should work.


Apologies for the late reply.



Re: Static constructor

2021-01-12 Thread ludo via Digitalmars-d-learn



NOTE : the entire code we are talking about is in the tiny url in 
my previous post.


On Thursday, 7 January 2021 at 01:55:07 UTC, SealabJaster wrote:

On Wednesday, 6 January 2021 at 17:05:02 UTC, ludo wrote:

...


Using a static class like this seems to mostly be a design 
decision.
So in otherwords, this class is essentially being used as a 
unique namespace for all of the other functions. Another way to 
look at it is just a singleton without a `.instance` getter.


Ok, I agree that ends up being a kind of strange singleton. But 
yes it was D v1 code. Do we agree that the following 
multi-threaded singleton pattern is the proper way as of today, 
instead of this static functions in a non static class (in 
multithreaded environment)?


shared(T) singleton()
{
 static shared T instance;

 if(!instance)
 {
   synchronized
   {
 if(!instance)
 instance = new shared(T)();
   }
 }

 return instance;
}
---



As for some of the other stuff, Associative Array literals in D 
can't actually be used at compile-time (at least, last time I 
tried), so they have to be created inside of the static 
constructor.


OK, I found 
https://dlang.org/spec/hash-map.html#static_initialization

Quote from that doc:
"Static Initialization of AAs
 NOTE: Not yet implemented. "
If I understand, as of today an AA init depends on a runtime 
function for historical reasons. A bit weird for an array indeed 
perfectly known at compile time, but someday some  core language 
contributor will have a look at it, I guess.




Next is the mutex. `Object` is the base class that every class 
in D will implicitly inherit from, like in C# for example. 
Object has a `.monitor` field which is basically just a mutex, 
so is used with multi-threading synchronisation. I find it a 
bit odd that they're just returning an object instead of a 
Mutex (module core.sync.mutex), but I'm sure there's a reason 
why.


If we consider the class from my first post, the comment coming 
with the getMutex func is following in the original code that I 
am "cleaning-up":
"Get an OpenAL mutex to ensure that no two threads ever execute 
OpenAL functionality simultaneously."


But the OpenAL class only has one function (anotherFunc), and as 
you say SealabJaster, it looks odd to use this Object mutex. I 
see two options to replace this mutex thing:
* make the entire class synchronized (writing "synchronized class 
OpenAL")
* make the anotherFunc function synchronized. So just one keyword 
to add!
If I understand well, this will accomplish the goal quoted with 
no further comestics needed! Only one keyword over explicitely 
using object mutex. Am I right?


Thanks



Re: Static constructor

2021-01-06 Thread SealabJaster via Digitalmars-d-learn

On Thursday, 7 January 2021 at 01:55:07 UTC, SealabJaster wrote:

...


And on a side note, I don't believe this code is working as the 
author intends.


Someone correct me if I'm wrong, but `static` variables in D 
arethread-local, so a `static Object mutex` wouldn't actually be 
visible between threads unless passed via some other means, and 
would instead act as a mutex-per-thread, sort of defying the 
point?


However `__gshared Object mutex` would likely be what they want?

I don't do much multithreaded stuff in D, so that information may 
or may not be correct.


Re: Static constructor

2021-01-06 Thread SealabJaster via Digitalmars-d-learn

On Wednesday, 6 January 2021 at 17:05:02 UTC, ludo wrote:

...


Using a static class like this seems to mostly be a design 
decision.


i.e. instead of using something like

```
openalGetMutex();

// OR

OpenAL openal = ...;
openal.getMutex();

// OR I guess even this

g_openal.getMutex();
```

They specifically want the interface to look like:

```
OpenAL.getMutex();
```

So in otherwords, this class is essentially being used as a 
unique namespace for all of the other functions. Another way to 
look at it is just a singleton without a `.instance` getter.


As for some of the other stuff, Associative Array literals in D 
can't actually be used at compile-time (at least, last time I 
tried), so they have to be created inside of the static 
constructor.


Next is the mutex. `Object` is the base class that every class in 
D will implicitly inherit from, like in C# for example. Object 
has a `.monitor` field which is basically just a mutex, so is 
used with multi-threading synchronisation. I find it a bit odd 
that they're just returning an object instead of a Mutex (module 
core.sync.mutex), but I'm sure there's a reason why.


(The README of this project states that this is a resurrection of 
some old project, and even refers to D as "Digital Mars", so this 
code may or may not have been built on a very old version of D 
originally.)


A better explanation of the monitor field can be found: 
https://forum.dlang.org/post/op.vqi9vrqueav7ka@steve-laptop


Hope this answers some questions.


Re: Static constructor

2021-01-06 Thread Imperatorn via Digitalmars-d-learn

On Wednesday, 6 January 2021 at 17:05:02 UTC, 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"


[...]


Since this is not the complete code it's a bit hard to know, but 
I'd guess this is for use as a singleton and/or for thread safety.


Re: static constructor not working with WinMain GUI app

2010-11-24 Thread Andrej Mitrovic
This means the windows sample code that comes with DMD in the samples
folder has to be updated, that's where I took the template from.

Thanks.

On 11/23/10, Simen kjaeraas simen.kja...@gmail.com wrote:
 Andrej Mitrovic n...@none.none wrote:

 maintest.def:
 EXETYPE NT
 SUBSYSTEM WINDOWS

 maintest.d:
 http://pastebin.com/3c4CKDG1

 Compiled with DMD 2.050:
 dmd maintest.d maintest.def

 The output in the log file is Lenght: 0. The static constructor is
 never called when using WinMain.

 But if I use a normal void main() function instead of WinMain, then
 the static constructor does get called. Here's a working example that
 tests a GUI dialogbox and outputs Length: 4 in the log file:

 maintest.def:
 EXETYPE NT
 SUBSYSTEM WINDOWS

 maintest.d:
 http://pastebin.com/3UDKmxJ1

 dmd maintest.d maintest.def

 This looks like a bug to me..

 Looking at http://digitalmars.com/d/2.0/windows.html, it seems your
 template for WinMain is outdated.

 You should use the template on that page, but beware that
 exceptionHandler should take a Throwable, not an Exception, like the
 example says. This error is reported:
 http://d.puremagic.com/issues/show_bug.cgi?id=5261

 --
 Simen



Re: static constructor not working with WinMain GUI app

2010-11-24 Thread Andrej Mitrovic
Ok I've filed a bug report and the fix:
http://d.puremagic.com/issues/show_bug.cgi?id=5268

On 11/24/10, Andrej Mitrovic andrej.mitrov...@gmail.com wrote:
 This means the windows sample code that comes with DMD in the samples
 folder has to be updated, that's where I took the template from.

 Thanks.

 On 11/23/10, Simen kjaeraas simen.kja...@gmail.com wrote:
 Andrej Mitrovic n...@none.none wrote:

 maintest.def:
 EXETYPE NT
 SUBSYSTEM WINDOWS

 maintest.d:
 http://pastebin.com/3c4CKDG1

 Compiled with DMD 2.050:
 dmd maintest.d maintest.def

 The output in the log file is Lenght: 0. The static constructor is
 never called when using WinMain.

 But if I use a normal void main() function instead of WinMain, then
 the static constructor does get called. Here's a working example that
 tests a GUI dialogbox and outputs Length: 4 in the log file:

 maintest.def:
 EXETYPE NT
 SUBSYSTEM WINDOWS

 maintest.d:
 http://pastebin.com/3UDKmxJ1

 dmd maintest.d maintest.def

 This looks like a bug to me..

 Looking at http://digitalmars.com/d/2.0/windows.html, it seems your
 template for WinMain is outdated.

 You should use the template on that page, but beware that
 exceptionHandler should take a Throwable, not an Exception, like the
 example says. This error is reported:
 http://d.puremagic.com/issues/show_bug.cgi?id=5261

 --
 Simen




Re: static constructor not working with WinMain GUI app

2010-11-23 Thread Simen kjaeraas

Andrej Mitrovic n...@none.none wrote:


maintest.def:
EXETYPE NT
SUBSYSTEM WINDOWS

maintest.d:
http://pastebin.com/3c4CKDG1

Compiled with DMD 2.050:
dmd maintest.d maintest.def

The output in the log file is Lenght: 0. The static constructor is  
never called when using WinMain.


But if I use a normal void main() function instead of WinMain, then  
the static constructor does get called. Here's a working example that  
tests a GUI dialogbox and outputs Length: 4 in the log file:


maintest.def:
EXETYPE NT
SUBSYSTEM WINDOWS

maintest.d:
http://pastebin.com/3UDKmxJ1

dmd maintest.d maintest.def

This looks like a bug to me..


Looking at http://digitalmars.com/d/2.0/windows.html, it seems your
template for WinMain is outdated.

You should use the template on that page, but beware that
exceptionHandler should take a Throwable, not an Exception, like the
example says. This error is reported:
http://d.puremagic.com/issues/show_bug.cgi?id=5261

--
Simen


Re: static constructor not working with WinMain GUI app

2010-11-23 Thread Michal Minich
On Tue, 23 Nov 2010 15:23:12 -0500, Andrej Mitrovic wrote:

 The static constructor is never called when using WinMain.

Make sure you use newest DMD, I think in 2.048 or 49 there was bug that 
module constructors were not called.