Singleton_pattern and Thread Safety

P

Pallav singh

HI All ,

i have a query using given singleton that its not thread Safe ?

Since function getInstance() is returning the static object singleton
class
AS far my knowlege, static object is intialized only first time when
control
reaches there. The second time control Thread reached there , compiler
skipps the initialization part.

http://en.wikipedia.org/wiki/Singleton_pattern

// This version solves the problems of the minimalist Singleton above,
// but strictly speaking only in a single-threaded environment,
// and use in a multithreaded environment when relying on the ABI
// may still pose problems at program termination time.

class Singleton
{
private:
Singleton() {}
~Singleton() {}
Singleton(const Singleton &); // intentionally undefined
Singleton & operator=(const Singleton &); // intentionally undefined

public:
static Singleton &getInstance();
};

// Source file (.cpp)
Singleton& Singleton::getInstance()
{
// Static Variables are initialized only first time Thread of
// Execution reaches here first time.
static Singleton instance;
return instance;
}

Thx
Pallav Singh
 
V

Victor Bazarov

HI All ,

i have a query using given singleton that its not thread Safe ?

Are you asking or are you telling?
Since function getInstance() is returning the static object singleton
class
AS far my knowlege, static object is intialized only first time when
control
reaches there. The second time control Thread reached there , compiler
skipps the initialization part.

Yes, usually. What's your query?

You probably need to get familiar with the problem of thread safety of
static object initialization. It's not very common, but it's been
studied enough to have left a trail that you could find using your
favorite Web search engine.
http://en.wikipedia.org/wiki/Singleton_pattern

// This version solves the problems of the minimalist Singleton above,
// but strictly speaking only in a single-threaded environment,
// and use in a multithreaded environment when relying on the ABI
// may still pose problems at program termination time.

class Singleton
{
private:
Singleton() {}
~Singleton() {}
Singleton(const Singleton&); // intentionally undefined
Singleton& operator=(const Singleton&); // intentionally undefined

public:
static Singleton&getInstance();
};

// Source file (.cpp)
Singleton& Singleton::getInstance()
{
// Static Variables are initialized only first time Thread of
// Execution reaches here first time.
static Singleton instance;
return instance;
}

Thx

Not sure for what...
Pallav Singh

V
 
M

Marcel Müller

Pallav said:
i have a query using given singleton that its not thread Safe ?

Since function getInstance() is returning the static object singleton
class
AS far my knowlege, static object is intialized only first time when
control
reaches there. The second time control Thread reached there , compiler
skipps the initialization part.

That's right.
// Source file (.cpp)
Singleton& Singleton::getInstance()
{
// Static Variables are initialized only first time Thread of
// Execution reaches here first time.
static Singleton instance;

This line is not guaranteed to be thread safe. In some implementation it
is safe.
return instance;
}


Marcel
 
J

James Kanze

That's right.
This line is not guaranteed to be thread safe. In some implementation it
is safe.

In practice, it will be thread safe *if* the first call to
getInstance occurs before threading starts. If threading
doesn't start before entering main (normally an acceptable
restriction), then just declaring a variable with static
lifetime which is initialized by getInstance() is sufficient,
e.g. (at namespace scope):

Singleton* dummyForInitialization = &Singleton::getInstance();

Note that the above still risks order of destruction issues;
it's more common to not destruct the singleton ever, with
something like:

namespace {

Singleton* ourInstance = &Singleton::instance();

Singleton&
Singleton::instance()
{
if (ourInstance == NULL)
ourInstance = new Singleton;
return *ourInstance;
}
}

(This solves both problems at once: initializing the variable
with a call to Singleton::instance and ensuring that the
singleton is never destructed.)
 
F

Fred Zwarts

Leigh Johnston said:
James "Cowboy" Kanze's OO designs includes objects that are never
destructed but leak instead? Interesting. What utter laziness
typical of somebody who probably overuses (abuses) the singleton
pattern. Singleton can be considered harmful (use rarely not
routinely).

As far as I can see it does not leak.
Up to the very end of the program the ourInstance pointer keeps pointing to the object
and can be used to access the object.
This is a well known technique to overcome the order of destruction issue.
 
U

u2

HI All ,

i have a query using given singleton that its not thread Safe ?

Since function getInstance() is returning the static  object singleton
class
AS far my knowlege, static object is intialized only first time when
control
reaches there. The second time control Thread reached there , compiler
skipps the initialization part.

http://en.wikipedia.org/wiki/Singleton_pattern

// This version solves the problems of the minimalist Singleton above,
// but strictly speaking only in a single-threaded environment,

It is not thread safe. The comment line you included says exactly
that.
What is your question?
 
F

Fred Zwarts

Leigh Johnston said:
Of course it is a memory leak the only upside being it is a singular
leak that would be cleaned up by the OS as part of program termination
rather than being an ongoing leak that continues to consume memory.

So, it is a matter of definition whether you want to call that a leak.
Usually something is acalled a leak if an object is no longer accessible,
because the pointer to the object went out of scope, or was assigned
a diferent value.
It is lazy. As far as it being a "well known technique" I have
encountered it before when working on a large project with many team
members but that does not justify its use; it was a consequence of
parallel development of many sub-modules with insufficient time set
aside for proper interop design and too much risk associated with
"fixing" it.

It is not necessarily lazy. The order of destruction of global objects
is not always predictable. Why spending time for a complex
solution, if it serves no purpose and makes the code much more
difficult to read?
Destruction is the opposite of construction; destruction (proper
cleanup) is not an intractable problem. /delete/ what you /new/.

Why? If destruction does not serve any purpose?
Is it a fixed rule so that you don't need to think about it?
 
J

James Kanze

[...]
James "Cowboy" Kanze's OO designs includes objects that are never
destructed but leak instead?

And where do you see a leak?
Interesting. What utter laziness typical
of somebody who probably overuses (abuses) the singleton pattern.

A lot of unsupported accusations from someone whose postings
here show a remarkable lack of any knowledge of serious software
engineering.
Singleton can be considered harmful (use rarely not routinely).

Does two or three in a program of 500KLoc count as "routinely"?
 
F

Fred Zwarts

Leigh Johnston said:
What do you mean by global objects? If you mean objects defined at
namespace scope or static class member objects then you should avoid
having such objects in more than one translation unit modulo the
advice that one should avoid globals as they are definitely
considered harmful. Singletons are nothing more than disguised
global variables.


If you can define construction then you can also define destruction;
why? Code re-use is one reason; e.g. a class which was initially a
singleton may suddenly be required to be instantiated more than once.
A class shouldn't really care about how many instances of it will be
created; ideally all objects should be destroyed on program
termination

should, shouldn't, ideally, ... It sounds like an ideology.
the only exceptions to this being abnormal program
termination (e.g. unhandled exception) or a program that is supposed
to never terminate.

Why don't you object against a program that never terminates?
Isn't that an even bigger leak?
Lazy?
If you can define a start voor a program, than you can define a stop.
Maybe later it may suddenly be required to be stopped.

Program termination and object termination (destruction) are comparable:
Don't waste your time in designing code for things you don't need.
I conclude it is a matter of taste whether it is called laziness of efficiency.
 
F

Fred Zwarts

Leigh Johnston said:
I see little difference between abnormal program termination and a
program that never terminates as far as system-wide object destruction
is concerned. If it is known in advance that a program never
terminates then one can relax the rules slightly if only for the sake
of efficiency if development time is a factor.

If it is known that an object never terminates, one may,
for the same reason, also relax the rules about destructors.
However, one should
always design a class so that is agnostic as to the amount instances
of it that will be made and that it can be explicitly destroyed. I
admit this is an ideal but if you design things properly in the first
place this should happen automatically (i.e. with little thought).

The same holds for coding program termination.
One can define rules here as well:
One should always design a program to be able to terminate properly.
If you design things properly in the first place, this should happen automatically.

But I understand that you are able to relax rules.
I respect such an opinion.
 
I

Ian Collins

James "Cowboy" Kanze's OO designs includes objects that are never
destructed but leak instead? Interesting. What utter laziness typical of
somebody who probably overuses (abuses) the singleton pattern. Singleton
can be considered harmful (use rarely not routinely).

What James describes is a very common idiom (to avoid order of
destruction issues) and it's certainly one I've often used.
 
I

Ian Collins

Not considering object destruction when designing *new* classes is bad
practice IMO. Obviously there may be problems when working with
pre-existing designs which were created with a lack of such consideration.

A programmer seldom has the benefit of a green field design. Even when
he or she does, there are still the dark and scary corners of the
language where undefined behaviour lurks. Order of destruction issues
is one such corner, especially when static objects exist in multiple
compilation units.

By the way, the leak example you posted differers in one significant
point from James' example above: the location of the allocation. James'
allocation takes place before main. I agree with my debugger in
categorising that as a "block in use" rather than a leek.
 
J

Joshua Maurice

I am well aware of the unspecified construction/destruction order
associated with globals in multiple TUs and that is primary reason why
this method of James's should be avoided.  The order of destruction of
"Meyers Singleton" objects *is* well defined for example although making
the "Meyers Singleton" method thread safe is not completely trivial.




It is a leak pure and simple; as I said else-thread if you use the
pattern in a DLL and load and unload the DLL multiple times the leak
will become apparent.  What some debugger chooses to name an allocation
is mostly irrelevant; it *is* an allocation without a paired deallocation..

So, under that particular pedantic definition, it is a memory leak.

Let me be a devil's advocate with the following questions. Have you
ever used fork and exec? Did you specifically "free" or "delete" /
every single outstanding allocation/ before calling exec? Just
wondering.

We disagree with your blanket assertion that memory leaks, under that
particular definition, are always bad and must be avoided at all
costs.

Your use case of loading and unloading the same DLL multiple times is
an interesting use case. I give you that point. I'll remember that in
the future as a particularly likely source of leaks.
 
I

Ian Collins

I am well aware of the unspecified construction/destruction order
associated with globals in multiple TUs and that is primary reason why
this method of James's should be avoided. The order of destruction of
"Meyers Singleton" objects *is* well defined for example although making
the "Meyers Singleton" method thread safe is not completely trivial.

That is another pattern I use, but as you say, it has issues of its own.
It is a leak pure and simple; as I said else-thread if you use the
pattern in a DLL and load and unload the DLL multiple times the leak
will become apparent.

Well that's something I have never done and can't see myself ever doing.
Why would you do it?
What some debugger chooses to name an allocation
is mostly irrelevant; it *is* an allocation without a paired deallocation.

It's not "some debugger", it's the opinion of the team that wrote the
debugger.
 
H

Howard Hinnant

 The order of destruction of
"Meyers Singleton" objects *is* well defined for example although making
the "Meyers Singleton" method thread safe is not completely trivial.

Just fyi the "Meyers Singleton" will be thread safe with a C++0x
conforming compiler (as currently drafted):

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3225.pdf

6.7 [stmt.dcl], paragraph 4:

.... If control enters the declaration concurrently while the variable
is being initialized, the concurrent execution shall wait for
completion of the initialization.^91 If control re-enters the
declaration recursively while the variable is being initialized, the
behavior is undefined.

91) The implementation must not introduce any deadlock around
execution of the initializer.

-Howard
 
J

Joshua Maurice

Royal we?  One word: Cowboy(s).

I am unsure if that is a sardonic remark or one made out of ignorance.
Are you that unaware of how every poster in this thread besides
yourself who commented on this issue is against you? That is to whom
the "we" referred.
 
I

Ian Collins

It is a leak pure and simple; as I said else-thread if you use the
pattern in a DLL and load and unload the DLL multiple times the leak
will become apparent. What some debugger chooses to name an allocation
is mostly irrelevant; it *is* an allocation without a paired deallocation.

It really come down to how you define a leak.

By my definition, a block is leaked when it becomes orphaned, either
when the last pointer to it is reassigned, or when the last pointer to
it goes out of scope (the two examples you posted).

The question then becomes how can a block assigned outside of main leak?

The last pointer to it can be reassigned inside main, so that would be a
leak. But it can't go out of scope without being freed by the operating
system. So it's a block in use immediately before the process terminates.

In your counter example of loading and unloading a dynamic library, all
the allocations are happening with main, so the last pointer can both be
reassigned and go out of scope. So you do have a leak, even if you only
load and unload once.
 
I

Ian Collins

A leak is a lack of a deallocation not the reassignment of the last
pointer to the object (which is just incidental to the leak). Remember
an object can delete itself (delete this) which means all pointers to it
can go out of scope / be reassigned and yet it is not leaked.

But memory allocated outside of main is deallocated, by the operating
system.
 
J

Joshua Maurice

Even though a memory barrier is emitted for a specific implementation of
my lockable class it obviously still relies on the C++ compiler not
re-ordering stores across a library I/O call (acquiring the lock) but it
works fine for me at least (VC++).  I could mention volatile but I
better not as that would start a long argument.  Roll on C++0x.

If I'm reading your code right, on the fast path, you don't have a
barrier, a lock, or any other kind of synchronization, right? If yes,
you realize you've coded the naive implementation of double checked?
You realize that it's broken, right? Have you even read
http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
?
To be clear, this has undefined behavior according to the C++0x
standard as well.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top