In this thread, the following is said about singleton instances:
The static variable can be static to the GetInstance() function, or it can be static in the Singleton class. There's interesting tradeoffs there.
What are these trade-offs? I am aware that, if declared as a static function variable, the singleton won't be constructed until the function is first called. I've also read something about thread-safety, but am unaware of what exactly that entails, or how the two approaches differ in that regard.
Are there any other major differences between the two? Which approach is better?
In my concrete example, I have a factory class set up as a singleton, and I'm storing the instance as a static const field in the class. I don't have a getInstance() method, but rather expect the user to access the instance directly, like so: ItemFactory::factory. The default constructor is private, and the instance is allocated statically.
Addendum: how good of an idea is it to overload operator() to call the createItem() method for the singleton, such that Items can be created like so: ItemFactory::factory("id")?
What are these trade-offs?
This is the most important consideration:
The static data member is initialized during the static initialization at the start of the program. If any static object depends on the singleton, then there will be a static initialization order fiasco.
The function local static object is initialized when the function is first called. Since whoever depends on the singleton will call the function, the singleton will be appropriately initialized and is not susceptible to the fiasco. There is still a - very subtle - problem with the destruction. If a destructor of a static object depends on the singleton, but the constructor of that object does not, then you'll end up with undefined behaviour.
Also, being initialized on the first time the function is called, means that the function may be called after the static initialization is done and main has been called. And therefore, the program may have spawned multiple threads. There could be a race condition on the initialization of the static local, resulting in multiple instances being constructed. Luckily, since C++11, the standard guarantees that the initialization is thread safe and this tradeoff no longer exists in conforming compilers.
Thread safety is not an issue with the static data member.
Which approach is better?
That depends on what your requirements are and what version of the standard you support.
I vote for static function variable. The newer C++ standard require automatic thread safety for initialization of such variables. It's implemented in GNU C++ for about ten years already. Visual Studio 2015 also supports this. If you make a static pointer variable holding reference to your singleton object, you'll have to deal with thread issues manually.
In the other hand, if you make a static member pointer field like shown in in the snippet below, you will be able to change it from other static methods, maybe re-init this field with other instance upon handling request to change program configuration. However, the snippet below contains a bug just to remind you how difficult multithreading is.
class ItemFactory {
static std::atomic_flag initialized = ATOMIC_FLAG_INIT;
static std::unique_ptr<ItemFactory> theFactoryInstance;
public:
static ItemFactory& getInstance() {
if (!initialized.test_and_set(std::memory_order_acquire)) {
theFactoryInstance = std::make_unique<ItemFactory>();
}
return *theFactoryInstance;
}
};
I wouldn't advise you to implement your singleton as a global non-pointer variable initialized before entry to the main() function. Thread safety issues will go away along with implicit cache coherency overhead, but you're not able to control the initialization order of your global variables in any precise or portable way.
Anyway, this choice doesn't force any permanent design implications. Since this instance will reside in the private section of your class you may always change it.
I don't think overloading of operator() for a factory is a good idea. operator() have "execute" semantics while in factory it's gonna stand for "create".
What is the best approach to a singleton in c++?
Hide the fact that it's a singleton and give it value semantics.
How?
All singleton-ness ought to be an implementation detail. In this way, consumers of your class need not refactor their programs if you need to change the way you implement your singleton (or indeed if you decide that it should not really be a singleton after all).
Why ?
Because now your program never has to worry itself with references, pointers, lifetimes and whatnot. It just uses an instance of the object as if it were a value. Safe in the knowledge that the singleton will take care of whatever lifetime/resource requirements it has.
What about a singleton that releases resources when not in use?
no problem.
Here's an example of the two approaches hidden behind the facade of an object with value semantics.
imagine this use case:
auto j1 = jobbie();
auto j2 = jobbie();
auto j3 = jobbie();
j1.log("doh");
j2.log("ray");
j3.log("me");
{
shared_file f;
f.log("hello");
}
{
shared_file().log("goodbye");
}
shared_file().log("here's another");
shared_file f2;
{
shared_file().log("no need to reopen");
shared_file().log("or here");
shared_file().log("or even here");
}
f2.log("all done");
where a jobbie object is just a facade for a singleton, but the shared_file object wants to flush/close itself when not in use.
so the output should look like this:
doh
ray
me
opening file
logging to file: hello
closing file
opening file
logging to file: goodbye
closing file
opening file
logging to file: here's another
closing file
opening file
logging to file: no need to reopen
logging to file: or here
logging to file: or even here
logging to file: all done
closing file
We can achieve this using the idiom, which I'll call 'value-semantics-is-a-facade-for-singleton':
#include <iostream>
#include <vector>
// interface
struct jobbie
{
void log(const std::string& s);
private:
// if we decide to make jobbie less singleton-like in future
// then as far as the interface is concerned the only change is here
// and since these items are private, it won't matter to consumers of the class
struct impl;
static impl& get();
};
// implementation
struct jobbie::impl
{
void log(const std::string& s) {
std::cout << s << std::endl;
}
};
auto jobbie::get() -> impl& {
//
// NOTE
// now you can change the singleton storage strategy simply by changing this code
// alternative 1:
static impl _;
return _;
// for example, we could use a weak_ptr which we lock and store the shared_ptr in the outer
// jobbie class. This would give us a shared singleton which releases resources when not in use
}
// implement non-singleton interface
void jobbie::log(const std::string& s)
{
get().log(s);
}
struct shared_file
{
shared_file();
void log(const std::string& s);
private:
struct impl;
static std::shared_ptr<impl> get();
std::shared_ptr<impl> _impl;
};
// private implementation
struct shared_file::impl {
// in a multithreaded program
// we require a condition variable to ensure that the shared resource is closed
// when we try to re-open it (race condition)
struct statics {
std::mutex m;
std::condition_variable cv;
bool still_open = false;
std::weak_ptr<impl> cache;
};
static statics& get_statics() {
static statics _;
return _;
}
impl() {
std::cout << "opening file\n";
}
~impl() {
std::cout << "closing file\n";
// close file here
// and now that it's closed, we can signal the singleton state that it can be
// reopened
auto& stats = get_statics();
// we *must* use a lock otherwise the compiler may re-order memory access
// across the memory fence
auto lock = std::unique_lock<std::mutex>(stats.m);
stats.still_open = false;
lock.unlock();
stats.cv.notify_one();
}
void log(const std::string& s) {
std::cout << "logging to file: " << s << std::endl;
}
};
auto shared_file::get() -> std::shared_ptr<impl>
{
auto& statics = impl::get_statics();
auto lock = std::unique_lock<std::mutex>(statics.m);
std::shared_ptr<impl> candidate;
statics.cv.wait(lock, [&statics, &candidate] {
return bool(candidate = statics.cache.lock())
or not statics.still_open;
});
if (candidate)
return candidate;
statics.cache = candidate = std::make_shared<impl>();
statics.still_open = true;
return candidate;
}
// interface implementation
shared_file::shared_file() : _impl(get()) {}
void shared_file::log(const std::string& s) { _impl->log(s); }
// test our class
auto main() -> int
{
using namespace std;
auto j1 = jobbie();
auto j2 = jobbie();
auto j3 = jobbie();
j1.log("doh");
j2.log("ray");
j3.log("me");
{
shared_file f;
f.log("hello");
}
{
shared_file().log("goodbye");
}
shared_file().log("here's another");
shared_file f2;
{
shared_file().log("no need to reopen");
shared_file().log("or here");
shared_file().log("or even here");
}
f2.log("all done");
return 0;
}
Related
In this thread, the following is said about singleton instances:
The static variable can be static to the GetInstance() function, or it can be static in the Singleton class. There's interesting tradeoffs there.
What are these trade-offs? I am aware that, if declared as a static function variable, the singleton won't be constructed until the function is first called. I've also read something about thread-safety, but am unaware of what exactly that entails, or how the two approaches differ in that regard.
Are there any other major differences between the two? Which approach is better?
In my concrete example, I have a factory class set up as a singleton, and I'm storing the instance as a static const field in the class. I don't have a getInstance() method, but rather expect the user to access the instance directly, like so: ItemFactory::factory. The default constructor is private, and the instance is allocated statically.
Addendum: how good of an idea is it to overload operator() to call the createItem() method for the singleton, such that Items can be created like so: ItemFactory::factory("id")?
What are these trade-offs?
This is the most important consideration:
The static data member is initialized during the static initialization at the start of the program. If any static object depends on the singleton, then there will be a static initialization order fiasco.
The function local static object is initialized when the function is first called. Since whoever depends on the singleton will call the function, the singleton will be appropriately initialized and is not susceptible to the fiasco. There is still a - very subtle - problem with the destruction. If a destructor of a static object depends on the singleton, but the constructor of that object does not, then you'll end up with undefined behaviour.
Also, being initialized on the first time the function is called, means that the function may be called after the static initialization is done and main has been called. And therefore, the program may have spawned multiple threads. There could be a race condition on the initialization of the static local, resulting in multiple instances being constructed. Luckily, since C++11, the standard guarantees that the initialization is thread safe and this tradeoff no longer exists in conforming compilers.
Thread safety is not an issue with the static data member.
Which approach is better?
That depends on what your requirements are and what version of the standard you support.
I vote for static function variable. The newer C++ standard require automatic thread safety for initialization of such variables. It's implemented in GNU C++ for about ten years already. Visual Studio 2015 also supports this. If you make a static pointer variable holding reference to your singleton object, you'll have to deal with thread issues manually.
In the other hand, if you make a static member pointer field like shown in in the snippet below, you will be able to change it from other static methods, maybe re-init this field with other instance upon handling request to change program configuration. However, the snippet below contains a bug just to remind you how difficult multithreading is.
class ItemFactory {
static std::atomic_flag initialized = ATOMIC_FLAG_INIT;
static std::unique_ptr<ItemFactory> theFactoryInstance;
public:
static ItemFactory& getInstance() {
if (!initialized.test_and_set(std::memory_order_acquire)) {
theFactoryInstance = std::make_unique<ItemFactory>();
}
return *theFactoryInstance;
}
};
I wouldn't advise you to implement your singleton as a global non-pointer variable initialized before entry to the main() function. Thread safety issues will go away along with implicit cache coherency overhead, but you're not able to control the initialization order of your global variables in any precise or portable way.
Anyway, this choice doesn't force any permanent design implications. Since this instance will reside in the private section of your class you may always change it.
I don't think overloading of operator() for a factory is a good idea. operator() have "execute" semantics while in factory it's gonna stand for "create".
What is the best approach to a singleton in c++?
Hide the fact that it's a singleton and give it value semantics.
How?
All singleton-ness ought to be an implementation detail. In this way, consumers of your class need not refactor their programs if you need to change the way you implement your singleton (or indeed if you decide that it should not really be a singleton after all).
Why ?
Because now your program never has to worry itself with references, pointers, lifetimes and whatnot. It just uses an instance of the object as if it were a value. Safe in the knowledge that the singleton will take care of whatever lifetime/resource requirements it has.
What about a singleton that releases resources when not in use?
no problem.
Here's an example of the two approaches hidden behind the facade of an object with value semantics.
imagine this use case:
auto j1 = jobbie();
auto j2 = jobbie();
auto j3 = jobbie();
j1.log("doh");
j2.log("ray");
j3.log("me");
{
shared_file f;
f.log("hello");
}
{
shared_file().log("goodbye");
}
shared_file().log("here's another");
shared_file f2;
{
shared_file().log("no need to reopen");
shared_file().log("or here");
shared_file().log("or even here");
}
f2.log("all done");
where a jobbie object is just a facade for a singleton, but the shared_file object wants to flush/close itself when not in use.
so the output should look like this:
doh
ray
me
opening file
logging to file: hello
closing file
opening file
logging to file: goodbye
closing file
opening file
logging to file: here's another
closing file
opening file
logging to file: no need to reopen
logging to file: or here
logging to file: or even here
logging to file: all done
closing file
We can achieve this using the idiom, which I'll call 'value-semantics-is-a-facade-for-singleton':
#include <iostream>
#include <vector>
// interface
struct jobbie
{
void log(const std::string& s);
private:
// if we decide to make jobbie less singleton-like in future
// then as far as the interface is concerned the only change is here
// and since these items are private, it won't matter to consumers of the class
struct impl;
static impl& get();
};
// implementation
struct jobbie::impl
{
void log(const std::string& s) {
std::cout << s << std::endl;
}
};
auto jobbie::get() -> impl& {
//
// NOTE
// now you can change the singleton storage strategy simply by changing this code
// alternative 1:
static impl _;
return _;
// for example, we could use a weak_ptr which we lock and store the shared_ptr in the outer
// jobbie class. This would give us a shared singleton which releases resources when not in use
}
// implement non-singleton interface
void jobbie::log(const std::string& s)
{
get().log(s);
}
struct shared_file
{
shared_file();
void log(const std::string& s);
private:
struct impl;
static std::shared_ptr<impl> get();
std::shared_ptr<impl> _impl;
};
// private implementation
struct shared_file::impl {
// in a multithreaded program
// we require a condition variable to ensure that the shared resource is closed
// when we try to re-open it (race condition)
struct statics {
std::mutex m;
std::condition_variable cv;
bool still_open = false;
std::weak_ptr<impl> cache;
};
static statics& get_statics() {
static statics _;
return _;
}
impl() {
std::cout << "opening file\n";
}
~impl() {
std::cout << "closing file\n";
// close file here
// and now that it's closed, we can signal the singleton state that it can be
// reopened
auto& stats = get_statics();
// we *must* use a lock otherwise the compiler may re-order memory access
// across the memory fence
auto lock = std::unique_lock<std::mutex>(stats.m);
stats.still_open = false;
lock.unlock();
stats.cv.notify_one();
}
void log(const std::string& s) {
std::cout << "logging to file: " << s << std::endl;
}
};
auto shared_file::get() -> std::shared_ptr<impl>
{
auto& statics = impl::get_statics();
auto lock = std::unique_lock<std::mutex>(statics.m);
std::shared_ptr<impl> candidate;
statics.cv.wait(lock, [&statics, &candidate] {
return bool(candidate = statics.cache.lock())
or not statics.still_open;
});
if (candidate)
return candidate;
statics.cache = candidate = std::make_shared<impl>();
statics.still_open = true;
return candidate;
}
// interface implementation
shared_file::shared_file() : _impl(get()) {}
void shared_file::log(const std::string& s) { _impl->log(s); }
// test our class
auto main() -> int
{
using namespace std;
auto j1 = jobbie();
auto j2 = jobbie();
auto j3 = jobbie();
j1.log("doh");
j2.log("ray");
j3.log("me");
{
shared_file f;
f.log("hello");
}
{
shared_file().log("goodbye");
}
shared_file().log("here's another");
shared_file f2;
{
shared_file().log("no need to reopen");
shared_file().log("or here");
shared_file().log("or even here");
}
f2.log("all done");
return 0;
}
I'm helping a student with their homework, which is a basic threading exercise. Unfortunately, though they're required to use C++11, they're forbidden from using std::thread. I don't see the rationale, but it's not my homework.
Here's the class:
class VaccineInfo {
public:
VaccineInfo(const std::string &t_input_filename):
input_filename(t_input_filename)
{ }
VaccineInfo() = delete;
static void *count_vaccines(void *t_vi);
int v1_count() { return vaccine_count["v1"]; }
int v2_count() { return vaccine_count["v2"]; }
int v3_count() { return vaccine_count["v3"]; }
private:
std::string input_filename;
std::map<std::string, int> vaccine_count {
{ "v1", 0 },
{ "v2", 0 },
{ "v3", 0 }
};
};
void *VaccineInfo::count_vaccines(void *t_vi) {
VaccineInfo *vi = reinterpret_cast<VaccineInfo*>(t_vi);
std::ifstream input_file;
std::string input_line;
input_file.open(vi->input_filename);
if (!input_file.good()) {
std::cerr << "No such file " << vi->input_filename << std::endl;
return nullptr;
}
while (std::getline(input_file, input_line)) {
vi->vaccine_count[input_line]++;
}
return nullptr;
}
And here's where pthreads comes in.
std::vector<std::string> filenames = find_filenames(".");
std::vector<pthread_t> thread_handles;
std::vector<VaccineInfo> vi_vector;
vi_vector.reserve(filenames.size());
for(const std::string &filename : filenames) {
pthread_t tid;
thread_handles.push_back(tid);
vi_vector.emplace_back(VaccineInfo(filename));
pthread_create(
&thread_handles.back(), nullptr, &VaccineInfo::count_vaccines,
static_cast<void*>(&vi_vector.back()));
}
for (const pthread_t tid : thread_handles) {
pthread_join(tid, nullptr);
}
It's a pretty basic exercise, except for how much fluff you have to do to get the old and the new to play nice. And that's what's got me wondering - does using a static member method as the start_routine argument to pthread_create have any undesirable side effects? I know static member variables and functions don't "belong" to any objects, but I normally think of static variables as being one-per-class, regardless of the number of objects. If there's only one copy of the static member function, as well, that seems like you'd be shooting yourself in the foot for parallelization.
Would it just be better, in this case, to make vaccine_count public and make count_vaccines() a global function?
Do hit me with whatever detail you can muster; I'm very curious. =) And, as always, thank you all for your time and effort.
except for how much fluff you have to do to get the old and the new to play nice.
Well, in the STL, that's essentially what the std::thread is actually doing. If you create a thread and force it to cause a stack unwinding, and if you look at said stack, you'll see a lot of weird pointer arithmetic happening with this and pthread_create (or CreateThread on Windows).
That being said, it's not unusual in any way to use a static function of a class that then calls a private member of that class on an object instance, even with the std::thread, it really just depends on what you need those functions to do.
does using a static member method as the start_routine argument to pthread_create have any undesirable side effects?
No. At least not from the perspective of functionality; that is, creating a thread on a static member won't cause any UB or crashes directly just because you are using a static function.
You do have to account for the fact that your operating on a static member function, but that's no different from having to account for constructors/destructors or any function of the language itself. Since this is a homework assignment, it's likely the professor is trying to teach "how things work" less than "how to use C++11".
Would it just be better, in this case, to make vaccine_count public and make count_vaccines() a global function?
Yes and no. Having vaccine_count as a private member then means that count_vaccines must be a friend or static function, and given that vaccine_count seems like an "important" data point that you wouldn't want a "user of the code" inadvertently setting, it's probably better to keep it private.
You could add getters and setters, but that might complicate the code unnecessarily.
You could also just make it a public variable if you trust the users of the code to protect that variable (unlikely), and you could also just make count_vaccines a free/global function, but then you need to have the function after the class declaration. And if the class is a complex class (maybe has templates or some other C++ notion), then it can really complicate the code in how you operate on the class.
So yes, it could go that way, but the professor is likely trying to teach the idea of what a static function is, how threads operate on the class and how pointers work within the constructs of this exercise, among other things.
If you have a static member variable, all objects access that variable.
That's not what static means in this context. The static keyword in C++ simply means that you do not need an object reference to call that code. So a static member variable can be accessed, not just by any object, but by any code, take this example:
class Data {
public:
static int x_val;
int y_val;
};
int Data::x_val; // have to declare it since it's static
int main(int argc, char* argv[]) {
Data::x_val = 10; // works because it's static.
Data::y_val = 10; // error: accessing a non-static member
Data obj;
obj.y_val = 10; // ok because it's a member variable
obj.x_val = 20; // this works as the complier ultimately translates this to `Data::x_val = 20`
// BUT, referencing a static member/function on an object instance is "bad form"
return 0;
}
If you have a static member function... can it be called on more than one core simultaneously?
The static keyword has no effect on which core, or thread, said function is called on or if can be done in parallel.
A CPU core can only execute 1 machine level instruction per clock cycle (so essentially, just 1 assembly instruction), when a C++ program is compiled, linked and assembled, it is these "assembled" set of instructions base on the syntax you wrote that are executed on the core (or cores) of your CPU, not the static functions.
That static function is just an address in memory that gets called on any number of threads on any CPU core that the OS determines at any given time in your program.
Yes, you could call an OS API that pins that thread of execution calling that function to a specific core, but that's a different subject.
And for a last little bit of fun for you, on an assembly level, C++ functions basically get compiled into C-like functions (an extreme over simplification, but merely for demonstration):
C++
class Data {
public:
void increment() {
this->y_val += 1024;
}
private:
int y_val;
};
int main() {
Data obj;
obj.y_val = 42;
obj.increment(); // obj.y_val == 1066
return 0;
}
C
struct Data {
int y_val;
};
void Data_increment(Data* this) {
this->y_val += 1024;
}
int main() {
Data obj;
obj.y_val = 42;
increment(&obj); // obj.y_val == 1066
return 0;
}
Again, an over simplification, but the point is to illustrate how it all builds to assembly and what the assembly does.
I have the following code:
Doc header file
class CMyDoc
{
public:
class Suspender
{
friend class CMyDoc;
static bool m_suspending;
inline static const bool IsSuspending() { return m_suspending; }
public:
Suspender()
{
m_suspending = true;
}
~Suspender()
{
m_suspending = false;
}
};
}
Doc source file
Static variable initialization:
bool CMyDoc::Suspender::m_suspending = false;
Check if it is on the "not allowed" to do things state, and if so, don't do them:
void CMyDoc::SomeMethod()
{
if (!Suspender::IsSuspending())
DoThings();
}
Somewhere where I want to run some code on the "not allowed" state
Declare a variable of the Suspender type. Automatically will put on the "not allowed state" on the declaration. But the greatest benefit is it will return itself back to the "allowed" state when the stack frame ends, as it passes on the s variable's destructor.
void CMyView::DoSomething()
{
CMyDoc::Suspender s;
((CMyDoc*) GetDocument())->SomeMethod();
}
QUESTIONS:
What is the name of the pattern?
Am I doing it in the most correct way? Can I avoid to have a static variable?
No, I don't think you are doing it in the most correct way, and because of the flaw in it I don't think its really RAII either.
The flaw I believe is there can be demonstrated without threads.
void SomeViewMethod()
{
Suspender s1;
((CMyDoc*) GetDocument())->SomeMethod();
}
SomeOtherViewMethod()
{
Suspender s2;
((CMyDoc*) GetDocument())->SomeMethod();
SomeViewMethod();
// this looks like suspender s2 should be suspending the next call...
// but when the s1 inside SomeViewMethod went out of scope it turned off suspending
((CMyDoc*) GetDocument())->SomeMethod();
}
This particular issue could be addressed by replacing the bool with an int to allow nested suspension. The int would be incremented by each suspender and suspension would be off if the value = 0.
(In the past I have successfully used such a pattern to control repetitive redraws)
1.) m_suspending is a property of CMyDoc because its behavior depends on it. Therefore it should be a member variable of CMyDoc.
2.) If Suspender can be created within multiple threads then m_suspending should be synchronized. And global variables are bad anyway.
3.) RAII is the keyword and your example looks similar to the way how mutex and lock_guard interact.
4.) You do not need a name for every trivial "pattern". RAII is fundamental in C++.
I've been trying to implement a singleton with some C++11 features from STL. I read about a few implementations and I found this pretty good: http://silviuardelean.ro/2012/06/05/few-singleton-approaches/ I made a few changes and got the bellow code working on VS2013, but I still would like to know:
a) Is this implementation thread-safe?
b) Is it ok (good practice) to return a shared_ptr from GetInstance instead of a reference?
PS.: My singleton is ment to be an OpenGL interface (that's the reason for the name).
HandlerOpenGL.h
#pragma once
// STL headers
#include <memory> // shared_ptr
#include <mutex> // once_flag
// OpenGL Handler Singleton
class HandlerOpenGL
{
public:
// Constructor/Destructor interface
static std::shared_ptr<HandlerOpenGL> GetInstance(void); // Only way to access singleton
~HandlerOpenGL(void);
HandlerOpenGL(const HandlerOpenGL&) = delete; // Avoid any copy/move
HandlerOpenGL(HandlerOpenGL&&) = delete;
HandlerOpenGL& operator=(const HandlerOpenGL&) = delete;
HandlerOpenGL& operator=(HandlerOpenGL&&) = delete;
private:
// Hide construction method/variables
HandlerOpenGL(void); // Private to be created once
static std::shared_ptr<HandlerOpenGL> _instance;
static std::once_flag _flag;
};
HandlerOpenGL.cpp
// Own header
#include "HandlerOpenGL.h"
// STL headers
#include <memory> // shared_ptr, make_shared
#include <mutex> // once_flag, call_once
// instanciate static members
std::shared_ptr<HandlerOpenGL> HandlerOpenGL::_instance(nullptr);
std::once_flag HandlerOpenGL::_flag;
std::shared_ptr<HandlerOpenGL> HandlerOpenGL::GetInstance(void)
{
std::call_once(_flag, [](){ _instance.reset(new HandlerOpenGL); });
return _instance;
}
HandlerOpenGL::~HandlerOpenGL(void)
{
}
HandlerOpenGL::HandlerOpenGL(void)
{
}
I do not see a point of using shared_ptr there at all. If it is a singleton, it will not be copied. So why use shared_ptr?
I also believe, a Meyers singleton is so much easier to do, requires less typing, and doesn't rely on dynamic allocation, so I wonder why would anybody would do anything else.
Despite all this, I do not see a specific threading issues with that.
I think using static variable at member function better than static member.
This "_instance" will be created once method called.
HandlerOpenGL& HandlerOpenGL::GetInstance(void)
{
static HandlerOpenGL _instance;
return _instance;
}
look at this
Pro tip - if you do think you need a singleton, give it value semantics and encapsulate its singleton nature as a private implementation detail.
In the future you may realise you don't need a singleton after all. If you wrote the class with value semantics, you wont have to change any user code - only the private implementation of the singleton:
struct HandlerOpenGL
{
// public interface
// note - allow it to be copyable.
// interface exists as instance method
void do_some_graphics();
private:
struct impl;
// this line is the only clue that singletons are involved
static auto get_impl() -> impl&;
};
// implementation (private)
struct HandlerOpenGL::impl
{
// this class holds your static data such as library pointers
// it can be non-moveable etc
impl()
{
// _gfx_engine = init_gfx_engine();
// if (!_gfx_engine)
// throw std::runtime_error("gfx engine failed to init");
}
~impl()
{
// commented out so that this example compiles with no
// external dependencies
// if (_gfx_engine)
// deinit_gfx_engine(_gfx_engine);
}
// gfx_engine * _gfx_engine;
};
// this is the private singleton-fetcher
auto HandlerOpenGL::get_impl() -> impl&
{
static impl _;
return _;
}
// implement the interface
void HandlerOpenGL::do_some_graphics()
{
// fetch my internal singleton
auto& static_data = get_impl();
// use methods and data in static_data here
// gfx_draw_surface(static_data._gfx_engine);
}
// now you can use it like a value - and it's decoupled from logic
// a function that renders graphics on any appropriate graphics engine
template<class T>
void some_graphic_render(T handler)
{
handler.do_some_graphics();
}
int main()
{
auto gfx = HandlerOpenGL(); // created trivially - behaves like a value
auto gfx2 = gfx; // copies no problem at all
// use as an argument to allow ADL - allows decoupling and dependency injection
some_graphic_render(gfx);
some_graphic_render(HandlerOpenGL()); // can even create as needed. no performance cost
return 0;
}
For debugging, I would like to add some counter variables to my class. But it would be nice to do it without changing the header to cause much recompiling.
If Ive understood the keyword correctly, the following two snippets would be quite identical. Assuming of course that there is only one instance.
class FooA
{
public:
FooA() : count(0) {}
~FooA() {}
void update()
{
++count;
}
private:
int count;
};
vs.
class FooB
{
public:
FooB() {}
~FooB() {}
void update()
{
static int count = 0;
++count;
}
};
In FooA, count can be accessed anywhere within the class, and also bloats the header, as the variable should be removed when not needed anymore.
In FooB, the variable is only visible within the one function where it exists. Easy to remove later. The only drawback I can think of is the fact that FooB's count is shared among all instances of the class, but thats not a problem in my case.
Is this correct use of the keyword? I assume that once count is created in FooB, it stays created and is not re-initialized to zero every call to update.
Are there any other caveats or headsup I should be aware of?
Edit: After being notified that this would cause problems in multithreaded environments, I clarify that my codebase is singlethreaded.
Your assumptions about static function variables are correct. If you access this from multiple threads, it may not be correct. Consider using InterlockedIncrement().
What you really want, for your long term C++ toolbox is a threadsafe, general purpose debug counters class that allows you to drop it in anywhere and use it, and be accessible from anywhere else to print it. If your code is performance sensitive, you probably want it to automatically do nothing in non-debug builds.
The interface for such a class would probably look like:
class Counters {
public:
// Counters singleton request pattern.
// Counters::get()["my-counter"]++;
static Counters& get() {
if (!_counters) _counters = new Counters();
}
// Bad idea if you want to deal with multithreaded things.
// If you do, either provide an Increment(int inc_by); function instead of this,
// or return some sort of atomic counter instead of an int.
int& operator[](const string& key) {
if (__DEBUG__) {
return _counter_map.operator[](key);
} else {
return _bogus;
}
}
// you have to deal with exposing iteration support.
private:
Counters() {}
// Kill copy and operator=
void Counters(const Counters&);
Counters& operator=(const Counters&);
// Singleton member.
static Counters* _counters;
// Map to store the counters.
std::map<string, int> _counter_map;
// Bogus counter for opt builds.
int _bogus;
};
Once you have this, you can drop it in at will wherever you want in your .cpp file by calling:
void Foo::update() {
// Leave this in permanently, it will automatically get killed in OPT.
Counters::get()["update-counter"]++;
}
And in your main, if you have built in iteration support, you do:
int main(...) {
...
for (Counters::const_iterator i = Counters::get().begin(); i != Countes::get().end(); ++i) {
cout << i.first << ": " << i.second;
}
...
}
Creating the counters class is somewhat heavy weight, but if you are doing a bunch of cpp coding, you may find it useful to write once and then be able to just link it in as part of any lib.
The major problems with static variables occur when they are used together with multi-threading. If your app is single-threaded, what you are doing is quite correct.
What I usually do in this situation is to put count in a anonymous namespace in the source file for the class. This means that you can add/remove the variable at will, it can can used anywhere in the file, and there is no chance of a name conflict. It does have the drawback that it can only be used in functions in the source file, not inlined functions in the header file, but I think that is what you want.
In file FooC.cpp
namespace {
int count=0;
}
void FooC::update()
{
++count;
}