| Thread overview | |||||||
|---|---|---|---|---|---|---|---|
|
August 09, 2006 Weird (?) problem | ||||
|---|---|---|---|---|
| ||||
Hi!
I've run into a big problem in my project, it's not really a problem with D, more a problem with ... you'll see.
Anyway: I've got a couple of classes in my project which represent type information (like MIDI notes, audio output, sample data, etc. - it'll be an audio app written in D). Basically it's a reflection system with some extras that are specific to this project.
Now, the idea is that every of these type classes has a static field which holds a single instance, like that:
' class TypeFoo : TypeBase
' {
' static TypeBase instance = null;
' static this() { instance = new TypeFoo(); }
' }
I've got a static opCall to return that instance:
' static TypeBase opCall() { return instance; }
Now everywhere I need to call an overloaded constructor or tell some object which type of other objects it can process, I just can call
' TypeFoo()
and get my type class.
Next is, I've got a namespace- or registry-like tree system, where all objects are stored into. That's where I store the information of "I can process objects of type X" too. It's somehow like:
' getObject("foo").setType(TypeFoo());
' getObject("foo").addCanProcess(TypeBar());
Now the thing is that the type classes need to identify themselves to the rest of the system as type classes. Therefore I've got a TypeType class. Which also resides in that tree.
Up until now I set up this information on my type classes via a "construct"-function, which was called at a point where the class instances already exist. But I'm a bit fed up of having to maintain two pieces of code (class definition and the construct-function), so I decided to make the type classes able to set up themselves. And here the trouble starts.
So: In the TypeType static c'tor, I make a new instance of that class. Then the normal c'tor is called, trying to setup itself in the tree system, telling everybody that it is indead a type. So ... it needs the very instance of the TypeType class that is being constructed at that very moment ... so: access violation.
' class TypeType : TypeBase
' {
' TypeBase instance = null;
' static this() { instance = new TypeType(); }
' static TypeBase opCall() { return instance; }
' this()
' {
' addObject("typetype");
' getObject("typetype").setType(TypeType()); // crashes: access violation
' }
' }
It's a bit of a chicken and egg problem. I can't new an instance of that class unless there's already one instance there. Is it possible to solve that somehow? Something like an "after_this()" or the like? I guess I've outsmarted myself there and I have no idea what to do about it besides reverting to the old system with that stupid, ugly construct function (shudder).
Any ideas would be really appreciated.
-Mike
--
Erstellt mit Operas revolutionärem E-Mail-Modul: http://www.opera.com/mail/
| ||||
August 10, 2006 Re: Weird (?) problem | ||||
|---|---|---|---|---|
| ||||
Posted in reply to mike | mike wrote: > Hi! > > I've run into a big problem in my project, it's not really a problem with D, more a problem with ... you'll see. > > Anyway: I've got a couple of classes in my project which represent type information (like MIDI notes, audio output, sample data, etc. - it'll be an audio app written in D). Basically it's a reflection system with some extras that are specific to this project. > > Now, the idea is that every of these type classes has a static field which holds a single instance, like that: > > ' class TypeFoo : TypeBase > ' { > ' static TypeBase instance = null; > ' static this() { instance = new TypeFoo(); } > ' } > > I've got a static opCall to return that instance: > > ' static TypeBase opCall() { return instance; } > > Now everywhere I need to call an overloaded constructor or tell some object which type of other objects it can process, I just can call > > ' TypeFoo() > > and get my type class. > > Next is, I've got a namespace- or registry-like tree system, where all objects are stored into. That's where I store the information of "I can process objects of type X" too. It's somehow like: > > ' getObject("foo").setType(TypeFoo()); > ' getObject("foo").addCanProcess(TypeBar()); > > Now the thing is that the type classes need to identify themselves to the rest of the system as type classes. Therefore I've got a TypeType class. Which also resides in that tree. > > Up until now I set up this information on my type classes via a "construct"-function, which was called at a point where the class instances already exist. But I'm a bit fed up of having to maintain two pieces of code (class definition and the construct-function), so I decided to make the type classes able to set up themselves. And here the trouble starts. > > So: In the TypeType static c'tor, I make a new instance of that class. Then the normal c'tor is called, trying to setup itself in the tree system, telling everybody that it is indead a type. So ... it needs the very instance of the TypeType class that is being constructed at that very moment ... so: access violation. > > ' class TypeType : TypeBase > ' { > ' TypeBase instance = null; > ' static this() { instance = new TypeType(); } > ' static TypeBase opCall() { return instance; } > ' this() > ' { > ' addObject("typetype"); > ' getObject("typetype").setType(TypeType()); // crashes: access violation > ' } > ' } > > It's a bit of a chicken and egg problem. I can't new an instance of that class unless there's already one instance there. Is it possible to solve that somehow? Something like an "after_this()" or the like? I guess I've outsmarted myself there and I have no idea what to do about it besides reverting to the old system with that stupid, ugly construct function (shudder). > > Any ideas would be really appreciated. > > -Mike > > --Erstellt mit Operas revolutionärem E-Mail-Modul: http://www.opera.com/mail/ Have you tried placing code after "instance = new TypeType()"? Like this: ' class TypeType : TypeBase ' { ' TypeBase instance = null; ' static this() { ' instance = new TypeType(); ' // I don't know whether addObject is a function ' // or a member of TypeType, but you get the point ' instance.addObject("typetype"); ' instance.getObject("typetype").setType(instance); ' } ' static TypeBase opCall() { return instance; } ' this() ' { ' } ' } Hope that helps (and works). Ary | |||
August 10, 2006 Re: Weird (?) problem | ||||
|---|---|---|---|---|
| ||||
Posted in reply to mike | mike wrote: > [snip] > > So: In the TypeType static c'tor, I make a new instance of that class. Then the normal c'tor is called, trying to setup itself in the tree system, telling everybody that it is indead a type. So ... it needs the very instance of the TypeType class that is being constructed at that very moment ... so: access violation. > > ' class TypeType : TypeBase > ' { > ' TypeBase instance = null; > ' static this() { instance = new TypeType(); } > ' static TypeBase opCall() { return instance; } > ' this() > ' { > ' addObject("typetype"); > ' getObject("typetype").setType(TypeType()); // crashes: access violation > ' } > ' } > > It's a bit of a chicken and egg problem. I can't new an instance of that class unless there's already one instance there. Is it possible to solve that somehow? Something like an "after_this()" or the like? I guess I've outsmarted myself there and I have no idea what to do about it besides reverting to the old system with that stupid, ugly construct function (shudder). > > Any ideas would be really appreciated. > > -Mike > Create two constructors for your TypeType classes. One private c'tor with a dummy parameter to differentiate it from the normal public c'tor. Call that private c'tor in your static c'tor; the private c'tor should obviously _not_ call into your registration system. The normal public c'tor should call the registration system, just like in your code above. class TypeType : TypeBase { TypeBase instance = null; static this() { instance = new TypeType(true); addObject("typetype"); addObject("typetype").setType(instance); } static TypeBase opCall() { return instance; } public this() { addObject("typetype"); getObject("typetype").setType(TypeType()); } private this(bool dummy) { // Just a dummy to suppress infinite recursion in constructor // calls... } } I'm curious as to the purpose of the multiple registration of the "typetype" named instance in your registry system. I hope you get the basic idea of what I'm proposing so you can fix these issues yourself. :) -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/MU/S d-pu s:+ a-->? C++++$ UL+++ P--- L+++ !E W-- N++ o? K? w--- O M--@ V? PS PE Y+ PGP- t+ 5 X+ !R tv-->!tv b- DI++(+) D++ G e++>e h>--->++ r+++ y+++ ------END GEEK CODE BLOCK------ James Dunne | |||
August 10, 2006 Re: Weird (?) problem | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ary Manzana | Thanks, it works! :-)
I still need one little workaround, but that's ok.
Funny thing is: Thinking about it a little bit more I got that idea:
' class TypeFoo : TypeBase
' {
' public:
' static this() { instance = new Bar(); }
'
' private:
' void setup() { /* add object, setup */ }
' TypeBase instance;
'
' unittest
' {
' instance.setup();
' }
' }
since the unittest will be executed after ALL static this()'s are done, and it's the only piece of code that is tied to a class and called automatically (besides the constructors) - but I don't want to be that evil :-)
Another question:
Is there a way to prevent a derived class from calling super()? I solved this currently with an empty this(int) and calling super(0), but is there another way?
-Mike
Am 10.08.2006, 14:14 Uhr, schrieb Ary Manzana <asterite@gmail.com>:
> Have you tried placing code after "instance = new TypeType()"?
>
> Like this:
>
> ' class TypeType : TypeBase
> ' {
> ' TypeBase instance = null;
> ' static this() {
> ' instance = new TypeType();
> ' // I don't know whether addObject is a function
> ' // or a member of TypeType, but you get the point
> ' instance.addObject("typetype");
> ' instance.getObject("typetype").setType(instance);
> ' }
> ' static TypeBase opCall() { return instance; }
> ' this()
> ' {
> ' }
> ' }
>
> Hope that helps (and works).
> Ary
--
Erstellt mit Operas revolutionärem E-Mail-Modul: http://www.opera.com/mail/
| |||
August 10, 2006 Re: Weird (?) problem | ||||
|---|---|---|---|---|
| ||||
Posted in reply to mike | mike wrote: > Thanks, it works! :-) > > I still need one little workaround, but that's ok. > > Funny thing is: Thinking about it a little bit more I got that idea: > > ' class TypeFoo : TypeBase > ' { > ' public: > ' static this() { instance = new Bar(); } > ' > ' private: > ' void setup() { /* add object, setup */ } > ' TypeBase instance; > ' > ' unittest > ' { > ' instance.setup(); > ' } > ' } > > since the unittest will be executed after ALL static this()'s are done, and it's the only piece of code that is tied to a class and called automatically (besides the constructors) - but I don't want to be that evil :-) Watch out!! Unit tests are only for debug purposes, once you compile your code with the "release" flag, no unit test will ever be invoked. > > Another question: > > Is there a way to prevent a derived class from calling super()? I solved this currently with an empty this(int) and calling super(0), but is there another way? I believe not, and it's because of the OOP philosophy... But you can always make a protected constructor for your derived classes, although this increases code dependency between classes, and I don't recommend it. > > -Mike > > > Am 10.08.2006, 14:14 Uhr, schrieb Ary Manzana <asterite@gmail.com>: > >> Have you tried placing code after "instance = new TypeType()"? >> >> Like this: >> >> ' class TypeType : TypeBase >> ' { >> ' TypeBase instance = null; >> ' static this() { >> ' instance = new TypeType(); >> ' // I don't know whether addObject is a function >> ' // or a member of TypeType, but you get the point >> ' instance.addObject("typetype"); >> ' instance.getObject("typetype").setType(instance); >> ' } >> ' static TypeBase opCall() { return instance; } >> ' this() >> ' { >> ' } >> ' } >> >> Hope that helps (and works). >> Ary > > > > --Erstellt mit Operas revolutionärem E-Mail-Modul: http://www.opera.com/mail/ | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply