FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

The Physics/Scene graph system...
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic     Forum Index -> ArcLib
View previous topic :: View next topic  
Author Message
clayasaurus



Joined: 21 May 2004
Posts: 857

PostPosted: Tue Apr 24, 2007 10:30 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
aldacron



Joined: 05 May 2004
Posts: 1322
Location: Seoul, South Korea

PostPosted: Tue Apr 24, 2007 10:54 am    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
ChristianK



Joined: 26 Sep 2006
Posts: 159
Location: Berlin, Germany

PostPosted: Tue Apr 24, 2007 11:19 am    Post subject: Reply with quote

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
View user's profile Send private message
aldacron



Joined: 05 May 2004
Posts: 1322
Location: Seoul, South Korea

PostPosted: Tue Apr 24, 2007 7:32 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
ChristianK



Joined: 26 Sep 2006
Posts: 159
Location: Berlin, Germany

PostPosted: Wed Apr 25, 2007 1:21 am    Post subject: Reply with quote

Quote:
You misunderstood. I was explaining to Clay why Derelict does not automatically load the shared libraries in module constructors.


Ah, okay. Smile

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
View user's profile Send private message
clayasaurus



Joined: 21 May 2004
Posts: 857

PostPosted: Wed Apr 25, 2007 12:36 pm    Post subject: Reply with 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 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
View user's profile Send private message AIM Address
clayasaurus



Joined: 21 May 2004
Posts: 857

PostPosted: Wed Apr 25, 2007 12:37 pm    Post subject: Reply with 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 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
View user's profile Send private message AIM Address
ChristianK



Joined: 26 Sep 2006
Posts: 159
Location: Berlin, Germany

PostPosted: Wed Apr 25, 2007 12:57 pm    Post subject: Reply with quote

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
View user's profile Send private message
clayasaurus



Joined: 21 May 2004
Posts: 857

PostPosted: Wed Apr 25, 2007 1:20 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
ChristianK



Joined: 26 Sep 2006
Posts: 159
Location: Berlin, Germany

PostPosted: Wed Apr 25, 2007 2:29 pm    Post subject: Reply with quote

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
View user's profile Send private message
clayasaurus



Joined: 21 May 2004
Posts: 857

PostPosted: Wed Apr 25, 2007 4:52 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
ChristianK



Joined: 26 Sep 2006
Posts: 159
Location: Berlin, Germany

PostPosted: Thu Apr 26, 2007 2:52 am    Post subject: Reply with quote

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
View user's profile Send private message
clayasaurus



Joined: 21 May 2004
Posts: 857

PostPosted: Thu Apr 26, 2007 9:03 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
ChristianK



Joined: 26 Sep 2006
Posts: 159
Location: Berlin, Germany

PostPosted: Thu Apr 26, 2007 9:55 am    Post subject: Reply with quote

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
View user's profile Send private message
clayasaurus



Joined: 21 May 2004
Posts: 857

PostPosted: Thu Apr 26, 2007 10:20 am    Post subject: Reply with quote

alright... code reverted back.
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> ArcLib All times are GMT - 6 Hours
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group