www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Singleton question (shared class)

reply "Mars" <- -.-> writes:
Hello everybody.
I have a few classes which I want to implement as singletons 
(like configuration, database connection, etc.), because I have 
to access them throughout my whole program, and from different 
threads. I'm implementing the singletons like this:
http://pastie.org/private/nltc3suxxuq6zyc6nqpdow
(I've read there's some bug if implementing them this way, but 
I'll deal with that later...)

Now to my actualy question/problem. My database (MySQL) class 
interfaces with C. So I constantly have to cast shared data, to 
get it in and out. And since I'm still a little insecure about 
shared, I'm wondering if that's okay. Example:
http://pastie.org/private/vd7qfh8b9c1chjnrimpp9a

If it's not... what's the right way to do this?

Mars
Jan 25 2012
next sibling parent "Mars" <- -.-> writes:
Alternative approach, I just found:
http://pastie.org/private/1jlcvfostnbopfp3quflg
If I get that right, this is basically the classic singleton, 
like it would be in other languages, right?
So... what's the best way?

Mars
Jan 25 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 25 Jan 2012 09:50:57 -0500, Mars <- -.-> wrote:

 Alternative approach, I just found:
 http://pastie.org/private/1jlcvfostnbopfp3quflg
 If I get that right, this is basically the classic singleton, like it  
 would be in other languages, right?
 So... what's the best way?

This is an ok approach, but you must handle all threading issues manually. In fact, you need to even with the shared version. I don't know how threading support works with MySQL, so it may be ok just to ignore threading issues. I'm not sure. Another approach is to use thread local storage to have a singleton per instance. This avoids the whole problem of sharing the instance. An issue with your singleton allocation, is that you don't do the check for the instance being null while synchronized. The singleton pattern looks like this: static T instance; T get() { if(instance is null) { synchronized if(instance is null) { instance = new T; } } return instance; } The second check is necessary to avoid allocating multiple instances (they will get thrown away, but no need to create them). Normally, you'd mark instance as volatile, but D2 doesn't support volatile any more. I don't know the correct way to make sure the second check isn't optimized out. -Steve
Jan 25 2012
prev sibling next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Wed, Jan 25, 2012 at 9:35 AM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 On Wed, 25 Jan 2012 09:50:57 -0500, Mars <- -.-> wrote:

 Alternative approach, I just found:
 http://pastie.org/private/1jlcvfostnbopfp3quflg
 If I get that right, this is basically the classic singleton, like it
 would be in other languages, right?
 So... what's the best way?

This is an ok approach, but you must handle all threading issues manually=

 =A0In fact, you need to even with the shared version. =A0I don't know how
 threading support works with MySQL, so it may be ok just to ignore thread=

 issues. =A0I'm not sure.

 Another approach is to use thread local storage to have a singleton per
 instance. =A0This avoids the whole problem of sharing the instance.

 An issue with your singleton allocation, is that you don't do the check f=

 the instance being null while synchronized. =A0The singleton pattern look=

 like this:

 static T instance;

 T get()
 {
 =A0 if(instance is null)
 =A0 {
 =A0 =A0 =A0synchronized if(instance is null)
 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0instance =3D new T;
 =A0 =A0 =A0}
 =A0 }
 =A0 return instance;
 }

 The second check is necessary to avoid allocating multiple instances (the=

 will get thrown away, but no need to create them).

 Normally, you'd mark instance as volatile, but D2 doesn't support volatil=

 any more. =A0I don't know the correct way to make sure the second check i=

 optimized out.

In the language spec, shared is supposed to guarantee this, but it currently doesn't. There was a conversation where pretty much every safe variant of the singleton pattern was discussed recently: http://www.digitalmars.com/d/archives/digitalmars/D/learn/Singleton_Pattern= _31406.html
Jan 25 2012
prev sibling next sibling parent "Mars" <- -.-> writes:
On Wednesday, 25 January 2012 at 23:40:38 UTC, Andrew Wiley wrote:
 In the language spec, shared is supposed to guarantee this, but 
 it
 currently doesn't. There was a conversation where pretty much 
 every
 safe variant of the singleton pattern was discussed recently:
 http://www.digitalmars.com/d/archives/digitalmars/D/learn/Singleton 
 Pattern 31406.html

Those are using shared though, which seems supoptimal for my needs (see first post). Mars
Jan 25 2012
prev sibling next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 01/25/2012 06:35 AM, Mars wrote:

 I have a few classes which I want to implement as singletons (like
 configuration, database connection, etc.), because I have to access them
 throughout my whole program, and from different threads.

You haven't asked, so I shouldn't be commenting on your design, but singleton is accepted as an anti-pattern for a long time now. It is more like a solution in search of a problem. For example, in your case, you can solve your problems by creating just one of those objects and pass them down to code that will use them. What prompted me to write this post is the following quote from the recent article of Pete Goodliffe in the ACCU's CVu magazine (volume 23, issue 6, January 2012): <quote="Pete Goodliffe"> In this little saunter through software complexity territory we've seen that complexity arises from blobs (our software components), lines (the connections between those components), but mostly from people (the muppets who construct these software disasters). Oh, and of course, it comes from the Singleton design pattern. But no one uses that any more, do they? </quote> Ali
Jan 26 2012
prev sibling parent "Mars" <- -.-> writes:
On Thursday, 26 January 2012 at 19:13:11 UTC, Ali Çehreli wrote:
 You haven't asked, so I shouldn't be commenting on your design, 
 but singleton is accepted as an anti-pattern for a long time 
 now. It is more like a solution in search of a problem. For 
 example, in your case, you can solve your problems by creating 
 just one of those objects and pass them down to code that will 
 use them.

 Ali

Thanks for your opinion. Although I know singletons aren't exactly best practice in OOP, I simply can't live without them. Sure I could pass my objects down again and again, so I have them availale at some point, but in a bigger program this just gets tedious, and for me that's not what OOP is supposed to do. On the contrey, things should get easier, and cleaner. Maybe I'll change my mind some day (5 years ago I though OOP was nonsense after all), or some new solution may come along, but for the time being, singletons are valid practice in my eyes. Mars
Jan 26 2012