View previous topic :: View next topic |
Author |
Message |
clayasaurus
Joined: 21 May 2004 Posts: 857
|
Posted: Tue Apr 24, 2007 10:30 am Post subject: |
|
|
I'm not sure about the static constructor
http://www.dsource.org/forums/viewtopic.php?t=2659&highlight=static+constructor
I remember there was some reason aldacron decided not to make the packages load automatically in derelict through static this(), because you can't control the order or some other problems. Or you can look at the above thread for more details, but it seems the recommendation is not to put derelict loading calls in the module constructors.
I'm fine with DerelictAL loading to be done in sound.open though |
|
Back to top |
|
|
aldacron
Joined: 05 May 2004 Posts: 1322 Location: Seoul, South Korea
|
Posted: Tue Apr 24, 2007 10:54 am Post subject: |
|
|
clayasaurus wrote: | I remember there was some reason aldacron decided not to make the packages load automatically in derelict through static this(), because you can't control the order or some other problems. |
When using a main() entry point, there's no way to handle exceptions thrown in module constructors. They will automatically cause the program to exit. One of the reasons Derelict uses manual loading of the shared libraries is to allow more flexibility in the case that the library fails to load. Not being able to catch any exceptions thrown during the load process defeats that purpose.
Quote: | Or you can look at the above thread for more details, but it seems the recommendation is not to put derelict loading calls in the module constructors. |
This is a side effect of the revamped loader system used internally. The initial implementation was based on free-functions (remember the Derelict*_Load syntax?). Tom reimplemented it using templates in order to ease maintenance and adding new packages. Unfortunately, building the Derelict libs and linking with them caused problems on Windows (thanks to OPTLINK's issues with templates). So he reimplemented the system such that loaders themselves are now just struct instances. Each module that declares a loader uses the module constructor to configure a pointer to that package's load function. The load then calls the given function pointer to actually load the shared library's functions.
A side effect, and something I hadn't really considered until the post you linked to came up, is that calling any Derelict*.load method in a module constructor outside of Derelict is highly dependent upon how the modules are loaded and processed at runtime. If a module that imports all of the Derelict modules you use is loaded before the one in which you call the load methods, then all is well. But if the load methods are called before the Derelict module constructors are run, the internal function pointer will not have been set and will cause an access violation.
I think I'm going to put a temporary fix in to throw an exception when that happens, so that people will at least know what's happening. Eventually, the internal loading system should probably be looked at again. In the meantime, you can call the Derelict*.load methods in the module constructor *if* you can guarantee that the Derelict module constructors are run first. My recommendation to avoid trying to do so is because I don't think you *can* guarantee that. It might work today, but break tomorrow because of a compiler update, or if you build on a different compiler, or even due to changes in your own code base. _________________ The One With D | The One With Aldacron | D Bits |
|
Back to top |
|
|
ChristianK
Joined: 26 Sep 2006 Posts: 159 Location: Berlin, Germany
|
Posted: Tue Apr 24, 2007 11:19 am Post subject: |
|
|
Quote: | there's no way to handle exceptions thrown in module constructors |
Well, yes - we would have to handle the exceptions within the module constructors. The situation is simple for OpenGL and SDL: if it fails to load, we will want to terminate with a descriptive error message. For OpenAL, I think we just want to disable the sound subsystem. That should be possible from within the module constructor.
Quote: | if the load methods are called before the Derelict module constructors are run, the internal delegate will not have been set and will cause an access violation. |
Wait, how can this happen?
Any module that wants to call DerelictGL.load will have to import derelict.opengl.gl, thereby requiring that derelict.opengl.gl's module constructor is run before its own module constructor. |
|
Back to top |
|
|
aldacron
Joined: 05 May 2004 Posts: 1322 Location: Seoul, South Korea
|
Posted: Tue Apr 24, 2007 7:32 pm Post subject: |
|
|
ChristianK wrote: | Quote: | there's no way to handle exceptions thrown in module constructors |
Well, yes - we would have to handle the exceptions within the module constructors. The situation is simple for OpenGL and SDL: if it fails to load, we will want to terminate with a descriptive error message. For OpenAL, I think we just want to disable the sound subsystem. That should be possible from within the module constructor. |
You misunderstood. I was explaining to Clay why Derelict does not automatically load the shared libraries in module constructors. If it did, users of Derelict would not be able to catch any exceptions that were thrown *by* Derelict in the Derelict constructors. Of course you can catch exceptions in your own app when you call Derelict*.load yourself.
Quote: | if the load methods are called before the Derelict module constructors are run, the internal delegate will not have been set and will cause an access violation. |
Wait, how can this happen?
Any module that wants to call DerelictGL.load will have to import derelict.opengl.gl, thereby requiring that derelict.opengl.gl's module constructor is run before its own module constructor.[/quote]
I went back and read the documentation module constructors and you're right. It should never happen. Unfortunately, it *did* happen for someone using DerelictIL. But yes, according to the spec, it should be safe to use module constructors to load Derelict. _________________ The One With D | The One With Aldacron | D Bits |
|
Back to top |
|
|
ChristianK
Joined: 26 Sep 2006 Posts: 159 Location: Berlin, Germany
|
Posted: Wed Apr 25, 2007 1:21 am Post subject: |
|
|
Quote: | You misunderstood. I was explaining to Clay why Derelict does not automatically load the shared libraries in module constructors. |
Ah, okay.
Quote: | It should never happen. Unfortunately, it *did* happen for someone using DerelictIL. |
Probably because of a compiler bug: this bug (http://d.puremagic.com/issues/show_bug.cgi?id=668) indicates that the order can get messed up if you're working with .di files. |
|
Back to top |
|
|
clayasaurus
Joined: 21 May 2004 Posts: 857
|
Posted: Wed Apr 25, 2007 12:36 pm Post subject: |
|
|
I moved the OpenAL derelict loading to arc.sound.open and fixed up the window unittest.
I also gave all the unittests less annoying names.
I'm thinking about moving the fontInit code to an arc.font.open and then put a stub arc.font.close
I'm also thinking about moving edianSwap from arc.window into arc.memory.routines |
|
Back to top |
|
|
clayasaurus
Joined: 21 May 2004 Posts: 857
|
Posted: Wed Apr 25, 2007 12:37 pm Post subject: |
|
|
I moved the OpenAL derelict loading to arc.sound.open and fixed up the window unittest.
I also gave all the unittests less annoying names.
I'm thinking about moving the fontInit code to an arc.font.open and then put a stub arc.font.close
I'm also thinking about moving edianSwap from arc.window into arc.memory.routines
I don't think we should load derelict from static constructor either. |
|
Back to top |
|
|
ChristianK
Joined: 26 Sep 2006 Posts: 159 Location: Berlin, Germany
|
Posted: Wed Apr 25, 2007 12:57 pm Post subject: |
|
|
Quote: | I moved the OpenAL derelict loading to arc.sound.open and fixed up the window unittest.
I also gave all the unittests less annoying names.
I'm also thinking about moving edianSwap from arc.window into arc.memory.routines |
Thanks and agreed.
Quote: | I don't think we should load derelict from static constructor either. |
Hm, I think we should since it simplifies user code. But not until that bug is fixed, for otherwise it'd preclude us from using derelict in a precompiled form. |
|
Back to top |
|
|
clayasaurus
Joined: 21 May 2004 Posts: 857
|
Posted: Wed Apr 25, 2007 1:20 pm Post subject: |
|
|
How does it simplify user code? The user will still need to call
arc.window.open/close and
and arc.sound.open/close
anyways, and this is where derelict load/unload currently is. |
|
Back to top |
|
|
ChristianK
Joined: 26 Sep 2006 Posts: 159 Location: Berlin, Germany
|
Posted: Wed Apr 25, 2007 2:29 pm Post subject: |
|
|
Quote: | How does it simplify user code? |
You can perform the sound init in a module constructor, probably also the font initialization. If you can use SDL_Surface and the image loading functions before having a window created, the user will also be able to load his static graphics data in module constructors. (check Asteroid.loadResources, where the asteroid data is loaded at the moment)
Not having to call any open/close functions (except for window.open) is a great advantage, in my opinion. |
|
Back to top |
|
|
clayasaurus
Joined: 21 May 2004 Posts: 857
|
Posted: Wed Apr 25, 2007 4:52 pm Post subject: |
|
|
Quote: |
You can perform the sound init in a module constructor, probably also the font initialization.
|
Right.
Quote: |
Not having to call any open/close functions (except for window.open) is a great advantage, in my opinion.
|
How will we handle the automatic calling of close functions? |
|
Back to top |
|
|
ChristianK
Joined: 26 Sep 2006 Posts: 159 Location: Berlin, Germany
|
Posted: Thu Apr 26, 2007 2:52 am Post subject: |
|
|
Quote: | How will we handle the automatic calling of close functions? |
The module destructors can do it.
I'm currently wondering about what to do when sound initialization fails (happens whenever something else is using sound output at the time for me). Ideally, the code would stay the same and just not do anything.
I think the standard solution is to have a sound class with two subclasses: one that contains the functionality and one whose implementations are empty.
But since our top-level modules are all class-less, it'd be odd to do that. There has to be a better solution than sticking a
Code: | if(!soundOn)
return; |
at the beginning of each and every function though. |
|
Back to top |
|
|
clayasaurus
Joined: 21 May 2004 Posts: 857
|
Posted: Thu Apr 26, 2007 9:03 am Post subject: |
|
|
Let's try out the static constructor / destructor and see how we like them. We should still keep the open() and close() functions, and then
static this()
{
open();
}
static ~this()
{
close();
}
Also, static constructors / destructor's prevent cyclic dependencies, which there may be in arc.
As for the sound problem, I'm not sure there is a better solution for sticking a if (!soundOn) return; That at least can be a short term solution.
edit: another problem is that with static constructors you can not give any options in the open() command, which are useful are window, log, and potentially input. hrm...
I'm thinking open / close are good for consistency, controlling the order that things are initialized / deinit, and potentially allowing for options on how to open the particular device.
edit: just changed window.close to close automatically and arc.log to open and close automatically .
Doing this, I had to comment out features in input.d and font.d that both use the window to handle things automatically. |
|
Back to top |
|
|
ChristianK
Joined: 26 Sep 2006 Posts: 159 Location: Berlin, Germany
|
Posted: Thu Apr 26, 2007 9:55 am Post subject: |
|
|
Wait!
The dmd bug that mixes up static constructor order if you use .di files is pretty major. Remember that if we switch to static constructors now and the bug isn't fixed by the time we want to release Arc 0.2, people will not be able to use precompiled arc or derelict.
I sorry for sounding like I want to use them now in one of the other posts: I don't. But when the time comes, I think it'll be a good option. |
|
Back to top |
|
|
clayasaurus
Joined: 21 May 2004 Posts: 857
|
Posted: Thu Apr 26, 2007 10:20 am Post subject: |
|
|
alright... code reverted back. |
|
Back to top |
|
|
|