My singleton can be called multiple times
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I have implemented an singleton based on c++ 11.
However the constructor can be called multiple times in some cases.
The class will be compiled to static lib and
used by other so lib (more than one so lib).
And the system is a multi-thread system (run in the Android HAL level)
/// The .h file:
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
/// the .cpp file
Logger::Logger()
{
ALOGE("OfflineLogger create");
}
Logger::~Logger()
{
}
It should be created once eg:
03-21 01:52:20.785 728 4522 E : OfflineLogger create
However I can see it has been created more than once
03-21 01:52:20.785 728 4522 E : OfflineLogger create
03-21 01:52:20.863 728 2274 E : OfflineLogger create
03-21 01:52:20.977 728 2273 E : OfflineLogger create
03-21 01:52:26.370 728 4522 E : OfflineLogger create
Questions:
Anything wrong with my singleton design? Is it a thread-safe issue?
Seems like my singleton works fine in one so scope, but each
so lib which includes my singleton will create its own singleton, so that my
singleton is no longer “be a singleton”. Is the problem caused from each
dynamic linking to new so and the "static variable" becomes "local static"?
Is it possible? If so, how to fix?
Thanks for any input!
add a comment |
I have implemented an singleton based on c++ 11.
However the constructor can be called multiple times in some cases.
The class will be compiled to static lib and
used by other so lib (more than one so lib).
And the system is a multi-thread system (run in the Android HAL level)
/// The .h file:
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
/// the .cpp file
Logger::Logger()
{
ALOGE("OfflineLogger create");
}
Logger::~Logger()
{
}
It should be created once eg:
03-21 01:52:20.785 728 4522 E : OfflineLogger create
However I can see it has been created more than once
03-21 01:52:20.785 728 4522 E : OfflineLogger create
03-21 01:52:20.863 728 2274 E : OfflineLogger create
03-21 01:52:20.977 728 2273 E : OfflineLogger create
03-21 01:52:26.370 728 4522 E : OfflineLogger create
Questions:
Anything wrong with my singleton design? Is it a thread-safe issue?
Seems like my singleton works fine in one so scope, but each
so lib which includes my singleton will create its own singleton, so that my
singleton is no longer “be a singleton”. Is the problem caused from each
dynamic linking to new so and the "static variable" becomes "local static"?
Is it possible? If so, how to fix?
Thanks for any input!
4
Don't forget to delete the copy constructor, otherwise it's easy to create multiple objects. It's a good idea to delete assignment, although it might not harm you too much to assign the object to itself
– Michael Veksler
Apr 2 at 6:11
1
Also don't forget that there's no synchronization employed here, so it's still prone to race conditions if it's ever used in a multi-threaded context.
– Alexander
Apr 2 at 10:33
1
@Alexander That applies to using the object and not to creating it, though. Since C++11, function-scope static variables are guaranteed to be initialised race-free.
– Angew
Apr 2 at 12:38
1
@Angew Woah, really? They finally have a purpose! That's great to hear
– Alexander
Apr 2 at 12:58
4
Here's an idea: Rather than use a singleton, which is both a hard problem in your environment and known to be problematic for testing and maintenance, just design your code to only create one of the object in question.
– T.E.D.
Apr 2 at 13:29
add a comment |
I have implemented an singleton based on c++ 11.
However the constructor can be called multiple times in some cases.
The class will be compiled to static lib and
used by other so lib (more than one so lib).
And the system is a multi-thread system (run in the Android HAL level)
/// The .h file:
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
/// the .cpp file
Logger::Logger()
{
ALOGE("OfflineLogger create");
}
Logger::~Logger()
{
}
It should be created once eg:
03-21 01:52:20.785 728 4522 E : OfflineLogger create
However I can see it has been created more than once
03-21 01:52:20.785 728 4522 E : OfflineLogger create
03-21 01:52:20.863 728 2274 E : OfflineLogger create
03-21 01:52:20.977 728 2273 E : OfflineLogger create
03-21 01:52:26.370 728 4522 E : OfflineLogger create
Questions:
Anything wrong with my singleton design? Is it a thread-safe issue?
Seems like my singleton works fine in one so scope, but each
so lib which includes my singleton will create its own singleton, so that my
singleton is no longer “be a singleton”. Is the problem caused from each
dynamic linking to new so and the "static variable" becomes "local static"?
Is it possible? If so, how to fix?
Thanks for any input!
I have implemented an singleton based on c++ 11.
However the constructor can be called multiple times in some cases.
The class will be compiled to static lib and
used by other so lib (more than one so lib).
And the system is a multi-thread system (run in the Android HAL level)
/// The .h file:
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
/// the .cpp file
Logger::Logger()
{
ALOGE("OfflineLogger create");
}
Logger::~Logger()
{
}
It should be created once eg:
03-21 01:52:20.785 728 4522 E : OfflineLogger create
However I can see it has been created more than once
03-21 01:52:20.785 728 4522 E : OfflineLogger create
03-21 01:52:20.863 728 2274 E : OfflineLogger create
03-21 01:52:20.977 728 2273 E : OfflineLogger create
03-21 01:52:26.370 728 4522 E : OfflineLogger create
Questions:
Anything wrong with my singleton design? Is it a thread-safe issue?
Seems like my singleton works fine in one so scope, but each
so lib which includes my singleton will create its own singleton, so that my
singleton is no longer “be a singleton”. Is the problem caused from each
dynamic linking to new so and the "static variable" becomes "local static"?
Is it possible? If so, how to fix?
Thanks for any input!
edited Apr 2 at 14:01
Fletch
166
166
asked Apr 2 at 5:02
hismarthismart
172210
172210
4
Don't forget to delete the copy constructor, otherwise it's easy to create multiple objects. It's a good idea to delete assignment, although it might not harm you too much to assign the object to itself
– Michael Veksler
Apr 2 at 6:11
1
Also don't forget that there's no synchronization employed here, so it's still prone to race conditions if it's ever used in a multi-threaded context.
– Alexander
Apr 2 at 10:33
1
@Alexander That applies to using the object and not to creating it, though. Since C++11, function-scope static variables are guaranteed to be initialised race-free.
– Angew
Apr 2 at 12:38
1
@Angew Woah, really? They finally have a purpose! That's great to hear
– Alexander
Apr 2 at 12:58
4
Here's an idea: Rather than use a singleton, which is both a hard problem in your environment and known to be problematic for testing and maintenance, just design your code to only create one of the object in question.
– T.E.D.
Apr 2 at 13:29
add a comment |
4
Don't forget to delete the copy constructor, otherwise it's easy to create multiple objects. It's a good idea to delete assignment, although it might not harm you too much to assign the object to itself
– Michael Veksler
Apr 2 at 6:11
1
Also don't forget that there's no synchronization employed here, so it's still prone to race conditions if it's ever used in a multi-threaded context.
– Alexander
Apr 2 at 10:33
1
@Alexander That applies to using the object and not to creating it, though. Since C++11, function-scope static variables are guaranteed to be initialised race-free.
– Angew
Apr 2 at 12:38
1
@Angew Woah, really? They finally have a purpose! That's great to hear
– Alexander
Apr 2 at 12:58
4
Here's an idea: Rather than use a singleton, which is both a hard problem in your environment and known to be problematic for testing and maintenance, just design your code to only create one of the object in question.
– T.E.D.
Apr 2 at 13:29
4
4
Don't forget to delete the copy constructor, otherwise it's easy to create multiple objects. It's a good idea to delete assignment, although it might not harm you too much to assign the object to itself
– Michael Veksler
Apr 2 at 6:11
Don't forget to delete the copy constructor, otherwise it's easy to create multiple objects. It's a good idea to delete assignment, although it might not harm you too much to assign the object to itself
– Michael Veksler
Apr 2 at 6:11
1
1
Also don't forget that there's no synchronization employed here, so it's still prone to race conditions if it's ever used in a multi-threaded context.
– Alexander
Apr 2 at 10:33
Also don't forget that there's no synchronization employed here, so it's still prone to race conditions if it's ever used in a multi-threaded context.
– Alexander
Apr 2 at 10:33
1
1
@Alexander That applies to using the object and not to creating it, though. Since C++11, function-scope static variables are guaranteed to be initialised race-free.
– Angew
Apr 2 at 12:38
@Alexander That applies to using the object and not to creating it, though. Since C++11, function-scope static variables are guaranteed to be initialised race-free.
– Angew
Apr 2 at 12:38
1
1
@Angew Woah, really? They finally have a purpose! That's great to hear
– Alexander
Apr 2 at 12:58
@Angew Woah, really? They finally have a purpose! That's great to hear
– Alexander
Apr 2 at 12:58
4
4
Here's an idea: Rather than use a singleton, which is both a hard problem in your environment and known to be problematic for testing and maintenance, just design your code to only create one of the object in question.
– T.E.D.
Apr 2 at 13:29
Here's an idea: Rather than use a singleton, which is both a hard problem in your environment and known to be problematic for testing and maintenance, just design your code to only create one of the object in question.
– T.E.D.
Apr 2 at 13:29
add a comment |
6 Answers
6
active
oldest
votes
- Anything wrong with my singleton design? Is it a thread-safe issue?
No. Initialization of function local static variables is guaranteed to be thread-safe by the standard.
- Seems like my singleton works fine in one so scope, but each
so lib which include my singleton will create its own singleton, so that my
singleton is no longer “be a singleton”. Is the problem caused from each
dynamic linking to new so and the "staic veriable" become "local static"?
Is it possible? If so, how to fix
That is the correct conclusion.
Instead of creating a static library that contains the implementation of the singleton, make it a dynamic library.
Thanks a lot for the help. Finally I change to use dynamic linking and works fine
– hismart
Apr 3 at 9:58
@hismart, you are welcome. Glad I was able to help.
– R Sahu
Apr 3 at 18:12
add a comment |
Singletons are hard, especially with shared libraries.
Each of your shared libraries has an independent copy of the non-shared library. Without extra care, each will have a copy of the singleton.
In order to have non-trivial singletons, what I have had to do was
Create an extremely low level library to help with singletons -- call it LibSingleton
Create a singleton template that knows the type of the singleton. It uses magic statics to send a request to the LibSingleton with a size,
typeid(T).name()key, and type-erased construction and destruction code. LibSingleton returns a reference counting RAII object.LibSingleton uses a shared mutex to either return a previously constructed object that matches the name/size or constructs it. If it constructs the object, it stores the destruction code.
When the last reference-counted handle to the LibSingleton data goes away, LibSingleton runs the destruction code and cleans up the memory in its unordered map.
This permits really simple singletons to be used nearly anywhere.
template<class T>
class singleton {
public:
static T& Instance() {
static auto smart_ptr = LibSingleton::RequestInstance(
typeid(T).name(),
sizeof(T),
(void* ptr){ return ::new( ptr ) T{}; },
(void* ptr){ static_cast<T*>(ptr)->~T(); }
);
if (!smart_ptr)
exit(-1); // or throw something
return *static_cast<T*>(smart_ptr.get());
}
protected:
singleton() = default;
~singleton() = default;
private:
singleton(singleton&&) = delete;
singleton& operator=(singleton&&) = delete;
};
use looks like:
struct Logger : LibSingleton::singleton<Logger> {
friend class LibSingleton::singleton<Logger>;
void do_log( char const* sting ) {}
private:
Logger() { /* ... */ }
};
4
Makes one wonder if having a Singleton is worth all that effort...
– Jared Smith
Apr 2 at 15:14
1
It looks like most of the effort is spent to get the first singleton, and others are relatively easy to add. Still, it makes one wonder ...
– David K
Apr 2 at 19:56
add a comment |
Here's an idea:Rather than use a singleton,which is both a hard problem in your environment and known to be problematic for testing and maintenance,just design your code to only create one of the object in question.
New contributor
Life School is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
7
Don't disagree, but this answer would be improved by an explanation of how...
– Jared Smith
Apr 2 at 15:15
add a comment |
Make it a global variable in a source file. That way you will only have one definition, even with static linking:
Anything wrong with my singleton design? Is it a thread-safe issue?
"Kind of" to the former, "No" for the latter
Seems like my singleton works fine in one so scope, but each so lib which include my singleton will create its own singleton, so that my singleton is no longer “be a singleton”. Is the problem caused from each dynamic linking to new so and the "staic veriable" become "local static"? Is it possible? If so, how to fix
If your GetInstance call is actually inlined it gives the compiler a free pass to create multiple definitions. If you declare it in a source file it will still cause trouble if you link against it as a static library multiple times.
This code should work
// Logger.cpp
Logger* gLoggerInstance = nullptr; // NOT STATIC
std::mutex gLoggerInstanceLock; // NOT STATIC, only if you need thread-safety
Logger& Logger::GetInstance() {
std::lock_guard(loggerInstanceLock); // only if you need thread-safety
if(!loggerInstance) loggerInstance = new Logger();
return *loggerInstance;
}
Edit: Only doesn't work with static libraries if you link the static libs into multiple DLLs that you then link into your executable:
A.lib
|
X.dll Y.dll
| /
G.exe
1
this will not work because each static lib has its own copy of global and static variables.
– hismart
Apr 3 at 7:39
add a comment |
static variable should be moved to .cpp file.
Simple way is to keep only declaration of getInstance() in .h and move implementation to .cpp file.
5
That won't help at all. Even inline functions are guaranteed to have only one set of statics. The problem here is with the shared libraries.
– Angew
Apr 2 at 12:39
add a comment |
It may be that your header file is being defined multiple times (it's the case if multiple files are including this header file. Try adding a guard around the header file to prevent it from being re-defined if it has already been defined once.
Depending on your C++ compiler, you could actually just add #pragma once as the first line in your file, like this
#pragma once
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
The intended effect is that of the most general alternative, which is to add a macro definition like this
#ifndef LOGGER_H
#define LOGGER_H
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
#endif LOGGER_H
6
Minor niggle: If you're using C++, you can just add#pragma onceshould be If you're using one of many common C++ compilers, you can just add#pragma once. When#pragma oncehas universal, Standard guaranteed support it will become#once.
– user4581301
Apr 2 at 5:15
1
Thanks for your hint. I already add the define but forgot to post it in here! I use your second solution.
– hismart
Apr 2 at 5:20
1
1. If that was the issue it would not compile ("redeclared class Logger") 2. This will not prevent multiple definitions of the static variable
– Benno Straub
Apr 2 at 11:35
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55467246%2fmy-singleton-can-be-called-multiple-times%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
- Anything wrong with my singleton design? Is it a thread-safe issue?
No. Initialization of function local static variables is guaranteed to be thread-safe by the standard.
- Seems like my singleton works fine in one so scope, but each
so lib which include my singleton will create its own singleton, so that my
singleton is no longer “be a singleton”. Is the problem caused from each
dynamic linking to new so and the "staic veriable" become "local static"?
Is it possible? If so, how to fix
That is the correct conclusion.
Instead of creating a static library that contains the implementation of the singleton, make it a dynamic library.
Thanks a lot for the help. Finally I change to use dynamic linking and works fine
– hismart
Apr 3 at 9:58
@hismart, you are welcome. Glad I was able to help.
– R Sahu
Apr 3 at 18:12
add a comment |
- Anything wrong with my singleton design? Is it a thread-safe issue?
No. Initialization of function local static variables is guaranteed to be thread-safe by the standard.
- Seems like my singleton works fine in one so scope, but each
so lib which include my singleton will create its own singleton, so that my
singleton is no longer “be a singleton”. Is the problem caused from each
dynamic linking to new so and the "staic veriable" become "local static"?
Is it possible? If so, how to fix
That is the correct conclusion.
Instead of creating a static library that contains the implementation of the singleton, make it a dynamic library.
Thanks a lot for the help. Finally I change to use dynamic linking and works fine
– hismart
Apr 3 at 9:58
@hismart, you are welcome. Glad I was able to help.
– R Sahu
Apr 3 at 18:12
add a comment |
- Anything wrong with my singleton design? Is it a thread-safe issue?
No. Initialization of function local static variables is guaranteed to be thread-safe by the standard.
- Seems like my singleton works fine in one so scope, but each
so lib which include my singleton will create its own singleton, so that my
singleton is no longer “be a singleton”. Is the problem caused from each
dynamic linking to new so and the "staic veriable" become "local static"?
Is it possible? If so, how to fix
That is the correct conclusion.
Instead of creating a static library that contains the implementation of the singleton, make it a dynamic library.
- Anything wrong with my singleton design? Is it a thread-safe issue?
No. Initialization of function local static variables is guaranteed to be thread-safe by the standard.
- Seems like my singleton works fine in one so scope, but each
so lib which include my singleton will create its own singleton, so that my
singleton is no longer “be a singleton”. Is the problem caused from each
dynamic linking to new so and the "staic veriable" become "local static"?
Is it possible? If so, how to fix
That is the correct conclusion.
Instead of creating a static library that contains the implementation of the singleton, make it a dynamic library.
answered Apr 2 at 5:08
R SahuR Sahu
171k1297195
171k1297195
Thanks a lot for the help. Finally I change to use dynamic linking and works fine
– hismart
Apr 3 at 9:58
@hismart, you are welcome. Glad I was able to help.
– R Sahu
Apr 3 at 18:12
add a comment |
Thanks a lot for the help. Finally I change to use dynamic linking and works fine
– hismart
Apr 3 at 9:58
@hismart, you are welcome. Glad I was able to help.
– R Sahu
Apr 3 at 18:12
Thanks a lot for the help. Finally I change to use dynamic linking and works fine
– hismart
Apr 3 at 9:58
Thanks a lot for the help. Finally I change to use dynamic linking and works fine
– hismart
Apr 3 at 9:58
@hismart, you are welcome. Glad I was able to help.
– R Sahu
Apr 3 at 18:12
@hismart, you are welcome. Glad I was able to help.
– R Sahu
Apr 3 at 18:12
add a comment |
Singletons are hard, especially with shared libraries.
Each of your shared libraries has an independent copy of the non-shared library. Without extra care, each will have a copy of the singleton.
In order to have non-trivial singletons, what I have had to do was
Create an extremely low level library to help with singletons -- call it LibSingleton
Create a singleton template that knows the type of the singleton. It uses magic statics to send a request to the LibSingleton with a size,
typeid(T).name()key, and type-erased construction and destruction code. LibSingleton returns a reference counting RAII object.LibSingleton uses a shared mutex to either return a previously constructed object that matches the name/size or constructs it. If it constructs the object, it stores the destruction code.
When the last reference-counted handle to the LibSingleton data goes away, LibSingleton runs the destruction code and cleans up the memory in its unordered map.
This permits really simple singletons to be used nearly anywhere.
template<class T>
class singleton {
public:
static T& Instance() {
static auto smart_ptr = LibSingleton::RequestInstance(
typeid(T).name(),
sizeof(T),
(void* ptr){ return ::new( ptr ) T{}; },
(void* ptr){ static_cast<T*>(ptr)->~T(); }
);
if (!smart_ptr)
exit(-1); // or throw something
return *static_cast<T*>(smart_ptr.get());
}
protected:
singleton() = default;
~singleton() = default;
private:
singleton(singleton&&) = delete;
singleton& operator=(singleton&&) = delete;
};
use looks like:
struct Logger : LibSingleton::singleton<Logger> {
friend class LibSingleton::singleton<Logger>;
void do_log( char const* sting ) {}
private:
Logger() { /* ... */ }
};
4
Makes one wonder if having a Singleton is worth all that effort...
– Jared Smith
Apr 2 at 15:14
1
It looks like most of the effort is spent to get the first singleton, and others are relatively easy to add. Still, it makes one wonder ...
– David K
Apr 2 at 19:56
add a comment |
Singletons are hard, especially with shared libraries.
Each of your shared libraries has an independent copy of the non-shared library. Without extra care, each will have a copy of the singleton.
In order to have non-trivial singletons, what I have had to do was
Create an extremely low level library to help with singletons -- call it LibSingleton
Create a singleton template that knows the type of the singleton. It uses magic statics to send a request to the LibSingleton with a size,
typeid(T).name()key, and type-erased construction and destruction code. LibSingleton returns a reference counting RAII object.LibSingleton uses a shared mutex to either return a previously constructed object that matches the name/size or constructs it. If it constructs the object, it stores the destruction code.
When the last reference-counted handle to the LibSingleton data goes away, LibSingleton runs the destruction code and cleans up the memory in its unordered map.
This permits really simple singletons to be used nearly anywhere.
template<class T>
class singleton {
public:
static T& Instance() {
static auto smart_ptr = LibSingleton::RequestInstance(
typeid(T).name(),
sizeof(T),
(void* ptr){ return ::new( ptr ) T{}; },
(void* ptr){ static_cast<T*>(ptr)->~T(); }
);
if (!smart_ptr)
exit(-1); // or throw something
return *static_cast<T*>(smart_ptr.get());
}
protected:
singleton() = default;
~singleton() = default;
private:
singleton(singleton&&) = delete;
singleton& operator=(singleton&&) = delete;
};
use looks like:
struct Logger : LibSingleton::singleton<Logger> {
friend class LibSingleton::singleton<Logger>;
void do_log( char const* sting ) {}
private:
Logger() { /* ... */ }
};
4
Makes one wonder if having a Singleton is worth all that effort...
– Jared Smith
Apr 2 at 15:14
1
It looks like most of the effort is spent to get the first singleton, and others are relatively easy to add. Still, it makes one wonder ...
– David K
Apr 2 at 19:56
add a comment |
Singletons are hard, especially with shared libraries.
Each of your shared libraries has an independent copy of the non-shared library. Without extra care, each will have a copy of the singleton.
In order to have non-trivial singletons, what I have had to do was
Create an extremely low level library to help with singletons -- call it LibSingleton
Create a singleton template that knows the type of the singleton. It uses magic statics to send a request to the LibSingleton with a size,
typeid(T).name()key, and type-erased construction and destruction code. LibSingleton returns a reference counting RAII object.LibSingleton uses a shared mutex to either return a previously constructed object that matches the name/size or constructs it. If it constructs the object, it stores the destruction code.
When the last reference-counted handle to the LibSingleton data goes away, LibSingleton runs the destruction code and cleans up the memory in its unordered map.
This permits really simple singletons to be used nearly anywhere.
template<class T>
class singleton {
public:
static T& Instance() {
static auto smart_ptr = LibSingleton::RequestInstance(
typeid(T).name(),
sizeof(T),
(void* ptr){ return ::new( ptr ) T{}; },
(void* ptr){ static_cast<T*>(ptr)->~T(); }
);
if (!smart_ptr)
exit(-1); // or throw something
return *static_cast<T*>(smart_ptr.get());
}
protected:
singleton() = default;
~singleton() = default;
private:
singleton(singleton&&) = delete;
singleton& operator=(singleton&&) = delete;
};
use looks like:
struct Logger : LibSingleton::singleton<Logger> {
friend class LibSingleton::singleton<Logger>;
void do_log( char const* sting ) {}
private:
Logger() { /* ... */ }
};
Singletons are hard, especially with shared libraries.
Each of your shared libraries has an independent copy of the non-shared library. Without extra care, each will have a copy of the singleton.
In order to have non-trivial singletons, what I have had to do was
Create an extremely low level library to help with singletons -- call it LibSingleton
Create a singleton template that knows the type of the singleton. It uses magic statics to send a request to the LibSingleton with a size,
typeid(T).name()key, and type-erased construction and destruction code. LibSingleton returns a reference counting RAII object.LibSingleton uses a shared mutex to either return a previously constructed object that matches the name/size or constructs it. If it constructs the object, it stores the destruction code.
When the last reference-counted handle to the LibSingleton data goes away, LibSingleton runs the destruction code and cleans up the memory in its unordered map.
This permits really simple singletons to be used nearly anywhere.
template<class T>
class singleton {
public:
static T& Instance() {
static auto smart_ptr = LibSingleton::RequestInstance(
typeid(T).name(),
sizeof(T),
(void* ptr){ return ::new( ptr ) T{}; },
(void* ptr){ static_cast<T*>(ptr)->~T(); }
);
if (!smart_ptr)
exit(-1); // or throw something
return *static_cast<T*>(smart_ptr.get());
}
protected:
singleton() = default;
~singleton() = default;
private:
singleton(singleton&&) = delete;
singleton& operator=(singleton&&) = delete;
};
use looks like:
struct Logger : LibSingleton::singleton<Logger> {
friend class LibSingleton::singleton<Logger>;
void do_log( char const* sting ) {}
private:
Logger() { /* ... */ }
};
edited Apr 2 at 16:04
answered Apr 2 at 14:36
Yakk - Adam NevraumontYakk - Adam Nevraumont
189k21199384
189k21199384
4
Makes one wonder if having a Singleton is worth all that effort...
– Jared Smith
Apr 2 at 15:14
1
It looks like most of the effort is spent to get the first singleton, and others are relatively easy to add. Still, it makes one wonder ...
– David K
Apr 2 at 19:56
add a comment |
4
Makes one wonder if having a Singleton is worth all that effort...
– Jared Smith
Apr 2 at 15:14
1
It looks like most of the effort is spent to get the first singleton, and others are relatively easy to add. Still, it makes one wonder ...
– David K
Apr 2 at 19:56
4
4
Makes one wonder if having a Singleton is worth all that effort...
– Jared Smith
Apr 2 at 15:14
Makes one wonder if having a Singleton is worth all that effort...
– Jared Smith
Apr 2 at 15:14
1
1
It looks like most of the effort is spent to get the first singleton, and others are relatively easy to add. Still, it makes one wonder ...
– David K
Apr 2 at 19:56
It looks like most of the effort is spent to get the first singleton, and others are relatively easy to add. Still, it makes one wonder ...
– David K
Apr 2 at 19:56
add a comment |
Here's an idea:Rather than use a singleton,which is both a hard problem in your environment and known to be problematic for testing and maintenance,just design your code to only create one of the object in question.
New contributor
Life School is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
7
Don't disagree, but this answer would be improved by an explanation of how...
– Jared Smith
Apr 2 at 15:15
add a comment |
Here's an idea:Rather than use a singleton,which is both a hard problem in your environment and known to be problematic for testing and maintenance,just design your code to only create one of the object in question.
New contributor
Life School is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
7
Don't disagree, but this answer would be improved by an explanation of how...
– Jared Smith
Apr 2 at 15:15
add a comment |
Here's an idea:Rather than use a singleton,which is both a hard problem in your environment and known to be problematic for testing and maintenance,just design your code to only create one of the object in question.
New contributor
Life School is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
Here's an idea:Rather than use a singleton,which is both a hard problem in your environment and known to be problematic for testing and maintenance,just design your code to only create one of the object in question.
New contributor
Life School is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
Life School is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
answered Apr 2 at 14:18
Life SchoolLife School
213
213
New contributor
Life School is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
Life School is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
Life School is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
7
Don't disagree, but this answer would be improved by an explanation of how...
– Jared Smith
Apr 2 at 15:15
add a comment |
7
Don't disagree, but this answer would be improved by an explanation of how...
– Jared Smith
Apr 2 at 15:15
7
7
Don't disagree, but this answer would be improved by an explanation of how...
– Jared Smith
Apr 2 at 15:15
Don't disagree, but this answer would be improved by an explanation of how...
– Jared Smith
Apr 2 at 15:15
add a comment |
Make it a global variable in a source file. That way you will only have one definition, even with static linking:
Anything wrong with my singleton design? Is it a thread-safe issue?
"Kind of" to the former, "No" for the latter
Seems like my singleton works fine in one so scope, but each so lib which include my singleton will create its own singleton, so that my singleton is no longer “be a singleton”. Is the problem caused from each dynamic linking to new so and the "staic veriable" become "local static"? Is it possible? If so, how to fix
If your GetInstance call is actually inlined it gives the compiler a free pass to create multiple definitions. If you declare it in a source file it will still cause trouble if you link against it as a static library multiple times.
This code should work
// Logger.cpp
Logger* gLoggerInstance = nullptr; // NOT STATIC
std::mutex gLoggerInstanceLock; // NOT STATIC, only if you need thread-safety
Logger& Logger::GetInstance() {
std::lock_guard(loggerInstanceLock); // only if you need thread-safety
if(!loggerInstance) loggerInstance = new Logger();
return *loggerInstance;
}
Edit: Only doesn't work with static libraries if you link the static libs into multiple DLLs that you then link into your executable:
A.lib
|
X.dll Y.dll
| /
G.exe
1
this will not work because each static lib has its own copy of global and static variables.
– hismart
Apr 3 at 7:39
add a comment |
Make it a global variable in a source file. That way you will only have one definition, even with static linking:
Anything wrong with my singleton design? Is it a thread-safe issue?
"Kind of" to the former, "No" for the latter
Seems like my singleton works fine in one so scope, but each so lib which include my singleton will create its own singleton, so that my singleton is no longer “be a singleton”. Is the problem caused from each dynamic linking to new so and the "staic veriable" become "local static"? Is it possible? If so, how to fix
If your GetInstance call is actually inlined it gives the compiler a free pass to create multiple definitions. If you declare it in a source file it will still cause trouble if you link against it as a static library multiple times.
This code should work
// Logger.cpp
Logger* gLoggerInstance = nullptr; // NOT STATIC
std::mutex gLoggerInstanceLock; // NOT STATIC, only if you need thread-safety
Logger& Logger::GetInstance() {
std::lock_guard(loggerInstanceLock); // only if you need thread-safety
if(!loggerInstance) loggerInstance = new Logger();
return *loggerInstance;
}
Edit: Only doesn't work with static libraries if you link the static libs into multiple DLLs that you then link into your executable:
A.lib
|
X.dll Y.dll
| /
G.exe
1
this will not work because each static lib has its own copy of global and static variables.
– hismart
Apr 3 at 7:39
add a comment |
Make it a global variable in a source file. That way you will only have one definition, even with static linking:
Anything wrong with my singleton design? Is it a thread-safe issue?
"Kind of" to the former, "No" for the latter
Seems like my singleton works fine in one so scope, but each so lib which include my singleton will create its own singleton, so that my singleton is no longer “be a singleton”. Is the problem caused from each dynamic linking to new so and the "staic veriable" become "local static"? Is it possible? If so, how to fix
If your GetInstance call is actually inlined it gives the compiler a free pass to create multiple definitions. If you declare it in a source file it will still cause trouble if you link against it as a static library multiple times.
This code should work
// Logger.cpp
Logger* gLoggerInstance = nullptr; // NOT STATIC
std::mutex gLoggerInstanceLock; // NOT STATIC, only if you need thread-safety
Logger& Logger::GetInstance() {
std::lock_guard(loggerInstanceLock); // only if you need thread-safety
if(!loggerInstance) loggerInstance = new Logger();
return *loggerInstance;
}
Edit: Only doesn't work with static libraries if you link the static libs into multiple DLLs that you then link into your executable:
A.lib
|
X.dll Y.dll
| /
G.exe
Make it a global variable in a source file. That way you will only have one definition, even with static linking:
Anything wrong with my singleton design? Is it a thread-safe issue?
"Kind of" to the former, "No" for the latter
Seems like my singleton works fine in one so scope, but each so lib which include my singleton will create its own singleton, so that my singleton is no longer “be a singleton”. Is the problem caused from each dynamic linking to new so and the "staic veriable" become "local static"? Is it possible? If so, how to fix
If your GetInstance call is actually inlined it gives the compiler a free pass to create multiple definitions. If you declare it in a source file it will still cause trouble if you link against it as a static library multiple times.
This code should work
// Logger.cpp
Logger* gLoggerInstance = nullptr; // NOT STATIC
std::mutex gLoggerInstanceLock; // NOT STATIC, only if you need thread-safety
Logger& Logger::GetInstance() {
std::lock_guard(loggerInstanceLock); // only if you need thread-safety
if(!loggerInstance) loggerInstance = new Logger();
return *loggerInstance;
}
Edit: Only doesn't work with static libraries if you link the static libs into multiple DLLs that you then link into your executable:
A.lib
|
X.dll Y.dll
| /
G.exe
edited Apr 3 at 7:55
answered Apr 2 at 11:52
Benno StraubBenno Straub
40879
40879
1
this will not work because each static lib has its own copy of global and static variables.
– hismart
Apr 3 at 7:39
add a comment |
1
this will not work because each static lib has its own copy of global and static variables.
– hismart
Apr 3 at 7:39
1
1
this will not work because each static lib has its own copy of global and static variables.
– hismart
Apr 3 at 7:39
this will not work because each static lib has its own copy of global and static variables.
– hismart
Apr 3 at 7:39
add a comment |
static variable should be moved to .cpp file.
Simple way is to keep only declaration of getInstance() in .h and move implementation to .cpp file.
5
That won't help at all. Even inline functions are guaranteed to have only one set of statics. The problem here is with the shared libraries.
– Angew
Apr 2 at 12:39
add a comment |
static variable should be moved to .cpp file.
Simple way is to keep only declaration of getInstance() in .h and move implementation to .cpp file.
5
That won't help at all. Even inline functions are guaranteed to have only one set of statics. The problem here is with the shared libraries.
– Angew
Apr 2 at 12:39
add a comment |
static variable should be moved to .cpp file.
Simple way is to keep only declaration of getInstance() in .h and move implementation to .cpp file.
static variable should be moved to .cpp file.
Simple way is to keep only declaration of getInstance() in .h and move implementation to .cpp file.
answered Apr 2 at 7:52
AIMIN PANAIMIN PAN
295210
295210
5
That won't help at all. Even inline functions are guaranteed to have only one set of statics. The problem here is with the shared libraries.
– Angew
Apr 2 at 12:39
add a comment |
5
That won't help at all. Even inline functions are guaranteed to have only one set of statics. The problem here is with the shared libraries.
– Angew
Apr 2 at 12:39
5
5
That won't help at all. Even inline functions are guaranteed to have only one set of statics. The problem here is with the shared libraries.
– Angew
Apr 2 at 12:39
That won't help at all. Even inline functions are guaranteed to have only one set of statics. The problem here is with the shared libraries.
– Angew
Apr 2 at 12:39
add a comment |
It may be that your header file is being defined multiple times (it's the case if multiple files are including this header file. Try adding a guard around the header file to prevent it from being re-defined if it has already been defined once.
Depending on your C++ compiler, you could actually just add #pragma once as the first line in your file, like this
#pragma once
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
The intended effect is that of the most general alternative, which is to add a macro definition like this
#ifndef LOGGER_H
#define LOGGER_H
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
#endif LOGGER_H
6
Minor niggle: If you're using C++, you can just add#pragma onceshould be If you're using one of many common C++ compilers, you can just add#pragma once. When#pragma oncehas universal, Standard guaranteed support it will become#once.
– user4581301
Apr 2 at 5:15
1
Thanks for your hint. I already add the define but forgot to post it in here! I use your second solution.
– hismart
Apr 2 at 5:20
1
1. If that was the issue it would not compile ("redeclared class Logger") 2. This will not prevent multiple definitions of the static variable
– Benno Straub
Apr 2 at 11:35
add a comment |
It may be that your header file is being defined multiple times (it's the case if multiple files are including this header file. Try adding a guard around the header file to prevent it from being re-defined if it has already been defined once.
Depending on your C++ compiler, you could actually just add #pragma once as the first line in your file, like this
#pragma once
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
The intended effect is that of the most general alternative, which is to add a macro definition like this
#ifndef LOGGER_H
#define LOGGER_H
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
#endif LOGGER_H
6
Minor niggle: If you're using C++, you can just add#pragma onceshould be If you're using one of many common C++ compilers, you can just add#pragma once. When#pragma oncehas universal, Standard guaranteed support it will become#once.
– user4581301
Apr 2 at 5:15
1
Thanks for your hint. I already add the define but forgot to post it in here! I use your second solution.
– hismart
Apr 2 at 5:20
1
1. If that was the issue it would not compile ("redeclared class Logger") 2. This will not prevent multiple definitions of the static variable
– Benno Straub
Apr 2 at 11:35
add a comment |
It may be that your header file is being defined multiple times (it's the case if multiple files are including this header file. Try adding a guard around the header file to prevent it from being re-defined if it has already been defined once.
Depending on your C++ compiler, you could actually just add #pragma once as the first line in your file, like this
#pragma once
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
The intended effect is that of the most general alternative, which is to add a macro definition like this
#ifndef LOGGER_H
#define LOGGER_H
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
#endif LOGGER_H
It may be that your header file is being defined multiple times (it's the case if multiple files are including this header file. Try adding a guard around the header file to prevent it from being re-defined if it has already been defined once.
Depending on your C++ compiler, you could actually just add #pragma once as the first line in your file, like this
#pragma once
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
The intended effect is that of the most general alternative, which is to add a macro definition like this
#ifndef LOGGER_H
#define LOGGER_H
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
#endif LOGGER_H
edited Apr 2 at 5:19
answered Apr 2 at 5:08
ribbitribbit
399311
399311
6
Minor niggle: If you're using C++, you can just add#pragma onceshould be If you're using one of many common C++ compilers, you can just add#pragma once. When#pragma oncehas universal, Standard guaranteed support it will become#once.
– user4581301
Apr 2 at 5:15
1
Thanks for your hint. I already add the define but forgot to post it in here! I use your second solution.
– hismart
Apr 2 at 5:20
1
1. If that was the issue it would not compile ("redeclared class Logger") 2. This will not prevent multiple definitions of the static variable
– Benno Straub
Apr 2 at 11:35
add a comment |
6
Minor niggle: If you're using C++, you can just add#pragma onceshould be If you're using one of many common C++ compilers, you can just add#pragma once. When#pragma oncehas universal, Standard guaranteed support it will become#once.
– user4581301
Apr 2 at 5:15
1
Thanks for your hint. I already add the define but forgot to post it in here! I use your second solution.
– hismart
Apr 2 at 5:20
1
1. If that was the issue it would not compile ("redeclared class Logger") 2. This will not prevent multiple definitions of the static variable
– Benno Straub
Apr 2 at 11:35
6
6
Minor niggle: If you're using C++, you can just add
#pragma once should be If you're using one of many common C++ compilers, you can just add #pragma once. When #pragma once has universal, Standard guaranteed support it will become #once.– user4581301
Apr 2 at 5:15
Minor niggle: If you're using C++, you can just add
#pragma once should be If you're using one of many common C++ compilers, you can just add #pragma once. When #pragma once has universal, Standard guaranteed support it will become #once.– user4581301
Apr 2 at 5:15
1
1
Thanks for your hint. I already add the define but forgot to post it in here! I use your second solution.
– hismart
Apr 2 at 5:20
Thanks for your hint. I already add the define but forgot to post it in here! I use your second solution.
– hismart
Apr 2 at 5:20
1
1
1. If that was the issue it would not compile ("redeclared class Logger") 2. This will not prevent multiple definitions of the static variable
– Benno Straub
Apr 2 at 11:35
1. If that was the issue it would not compile ("redeclared class Logger") 2. This will not prevent multiple definitions of the static variable
– Benno Straub
Apr 2 at 11:35
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55467246%2fmy-singleton-can-be-called-multiple-times%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
Don't forget to delete the copy constructor, otherwise it's easy to create multiple objects. It's a good idea to delete assignment, although it might not harm you too much to assign the object to itself
– Michael Veksler
Apr 2 at 6:11
1
Also don't forget that there's no synchronization employed here, so it's still prone to race conditions if it's ever used in a multi-threaded context.
– Alexander
Apr 2 at 10:33
1
@Alexander That applies to using the object and not to creating it, though. Since C++11, function-scope static variables are guaranteed to be initialised race-free.
– Angew
Apr 2 at 12:38
1
@Angew Woah, really? They finally have a purpose! That's great to hear
– Alexander
Apr 2 at 12:58
4
Here's an idea: Rather than use a singleton, which is both a hard problem in your environment and known to be problematic for testing and maintenance, just design your code to only create one of the object in question.
– T.E.D.
Apr 2 at 13:29