Thread overview
Singleton question (shared class)
Jan 25, 2012
Mars
Jan 25, 2012
Mars
Jan 25, 2012
Andrew Wiley
Jan 26, 2012
Mars
Jan 26, 2012
Ali Çehreli
Jan 26, 2012
Mars
January 25, 2012
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
January 25, 2012
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
January 25, 2012
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
January 25, 2012
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.  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.

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
January 26, 2012
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
January 26, 2012
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

January 26, 2012
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