This question already has answers here:
Undefined reference to static class member
(9 answers)
Closed 8 years ago.
I have implemented a Meyer's singleton pattern. And I try to do some stuff testing it in a multithreading environment. Here is how I implemented the class in C++.
#include<thread>
#include<mutex>
class singleton {
public:
static singleton& instance() {
std::lock_guard<std::mutex> lck(mtx);
static singleton *my = new singleton;
return *my;
}
private:
static std::mutex mtx;
singleton() {}
~singleton() {}
singleton(const singleton &) {}
singleton& operator=(const singleton &) {}
};
But when I compile this with g++ -std=c++11 singleton.cpp -o singleton -lpthread, it says
/tmp/ccfEBnmN.o: In function `singleton::instance()':
singleton.cpp(.text._ZN11singleton12instanceEv[_ZN11singelton12instanceEv]+0x10):
undefined reference to `singleton::mtx' collect2: error: ld returned 1 exit status
I understand this might be some problem in design, since without initializing the first singleton instance how could we get the mtx. If in this case, my question comes to how to implement a thread safe singleton class based on my code? How do we initialized the mtx in my singleton class?
I know there is a traditional way to create a singleton pattern by maintaining a static pointer points to the singleton class. But indeed that is not "so" thread safe. Even applying the double check mechanism in the instance() method.
You've declared mtx in singleton, but failed to define it, which has to be outside of singleton, something like this:
std::mutex singleton::mtx;
This should be in a source file, not a header though (otherwise you'll get multiple definition errors when/if you include the header in more than one source file).
Second point: what you're showing is not a Meyer's singleton pattern at all. For a Meyer's singleton, you define a static instance of the singleton inside the function:
static singleton &instance() {
static singleton my;
return my;
}
Using this, it's not clear that you really need a mutex at all.
Your static data member mtx needs a definition. Place this in your source file:
std::mutex singleton::mtx;
More accurately, std::lock_guard<std::mutex> lck(mtx) odr-uses mtx so its definition is required. You get a link-time error when the linker cannot resolve the reference.
Also note that in C++11 the initialization of an object with static storage duration is thread safe, you don't need a mutex.
Related
This question already has answers here:
C++ singleton vs. global static object
(8 answers)
Closed 5 years ago.
I know that singleton allow only one instance of an object. Each method declared in the singleton will only operate on this object.
I was wondering why to not simply declare a global object which will achieve the same goal?
I am certainly forgetting something. If singletons exist there must be specific uses or help to realize specific mechanisms.
For instance:
class Singleton
{
public:
static Singleton& Instance()
{
static Singleton sg;
return sg;
}
void function();
};
would be the same as:
class NotSingleton
{
public:
NotSingleon();
~NotSingleton()
void function();
};
NotSingleton nsg;
However, nothing prevent me to use more than one instance of NotSingleton
Singleton is used when we do not want to create more than one object. Singleton class ensures that not more than one object is created. However, having a global object doesn't ensure this.
class Singleton {
public static Singleton object = null;
public void singleton() {
if (object == null)
object = new Singleton();
return object;
}
}
This class will not create more than one object. This is the purpose of the Singleton class.
This question already has answers here:
C++11 "auto" semantics
(3 answers)
Closed 6 years ago.
I am writing a simple garbage collector in C++. I need a singleton class GarbageCollector to deal with different types of memory.
I used a Meyer's singleton pattern. But when I try to call instance, an error appears:
error: ‘GarbageCollector::GarbageCollector(const GarbageCollector&)’ is private
GarbageCollector(const GarbageCollector&);
^
Here is the class definition.
class GarbageCollector //Meyers singleton (http://cpp-reference.ru/patterns/creational-patterns/singleton/)
{
public:
static GarbageCollector& instance(){
static GarbageCollector gc;
return gc;
}
size_t allocated_heap_memory;
size_t max_heap_memory;
private:
//Copying, = and new are not available to be used by user.
GarbageCollector(){};
GarbageCollector(const GarbageCollector&);
GarbageCollector& operator=(GarbageCollector&);
};
I call the instance with the following line:
auto gc = GarbageCollector::instance();
Change
auto gc = GarbageCollector::instance();
to
auto& gc = GarbageCollector::instance();
Otherwise gc is not a reference, then returned GarbageCollector need to be copied, but the copy ctor is private, that's why compiler complains.
This question already has answers here:
Is Meyers' implementation of the Singleton pattern thread safe?
(6 answers)
Closed 6 years ago.
I've seen posts about this issue but I'm still trying to figure it out. Is this way alright for implementing a safe singelton? I'm using mutex, static member and return its reference.
#include <mutex>
using namespace std;
mutex mtx;
class MySingleton {
private:
MySingleton();
public:
MySingleton& getInstance() {
mtx.lock();
static MySingleton instance;
mtx.unlock();
return instance;
}
};
Is this way alright for implementing a safe singelton?
It's overshoot. Just get rid of the mutex and write:
static MySingleton& getInstance() {
static MySingleton instance;
return instance;
}
The thread safe creation of instance is guaranteed when the function is called the 1st time.
This question already has answers here:
How to initialize private static members in C++?
(18 answers)
Closed 9 years ago.
So I have the following c++ class
class MyClass:
public:
static void InitObject();
private:
static MyObject *myObject;
};
And then in the .cpp file I do
void MyClass::InitObject
{
myObject = new MyObject();
}
However, I get a compiler error saying that "myObject" was referenced from InitObject() and then it says Linker command failed with exit code 1.
Why doesn't this work? How do I fix it?
Since static data members of classes in C++ need memory space that is separate from the instance memory, they need to be defined, in addition to being declared in the class.
You do that in a separate translation unit (in your CPP file) like this:
MyObject *MyClass::myObject;
This definition tells the compiler to allocate space for myObject in the static memory area. Without this definition, the code is going to compile, but the linker will report an error, because it is responsible for ensuring that all referenced static objects have memory allocated to them.
Extend your .cpp file with the following definition for myObject:
MyObject* MyObject::myObject = NULL;
NOTE:
For your particular case you might be better off saying:
class MyClass:
{
public:
static MyClass& instance();
private:
MyClass() {}
};
and in .cpp file:
MyClass& MyClass::instance()
{
static MyClass myInstance;
return myInstance;
}
I'd prefer this over using new MyClass(). Any access to the instance() method will guarantee your instance is initialized exactly once, and you'll get a valid reference to it.
'Space' is completely allocated on the stack then, as well for the reference as for the instance itself.
You never allocated space for MyObject::myObject. Put this in the CPP file:
MyObject* MyObject::myObject;
This question already has answers here:
Undefined reference to static class member
(9 answers)
C++ - Initialize and modify a static class member
(4 answers)
Closed 9 years ago.
I have problem with pthread_mutex_t. When I try to create static field pthread_mutex_t, then initialize it in static function and finally use it within some class methods I get many errors like:
main.o: In function `LogWriter::initialize(pthread_mutex_t*)':
main.cpp:(.text._ZN9LogWriter10initializeEP15pthread_mutex_t[LogWriter::initialize(pthread_mutex_t*)]+0x7): undefined reference to `LogWriter::mutex'
Simpplified class code:
class LogWriter{
static pthread_mutex_t mutex;
static void initialize(pthread_mutex_t *mut){
LogWriter::mutex = PTHREAD_MUTEX_INITIALIZER;
//if(pthread_mutex_init(&(LogWriter::mutex), NULL) != 0){
//init failed
//}
}
public:
static LogWriter getInstance(string module_name){
LogWriter instance(module_name);
return instance;
}
LogWriter& operator<<(string a);
};
My quesiton is: why ? I know that if I define it as normal (non-static) field I won't have any problems. Also searched google but I couldn't find any materials that are linked with this.
Also creating pointer to static pthread_mutex and initializing in in main function ends like this.
In some source file in your code, you need to add:
static LogWriter::pthread_mutex_t mutex;
The compiler won't "place" your variable in any particular source file, you have to do that for it. The class declaration just tells the compiler "I'll have a static variable somewhere" - but since, at least in theory, variables ordering and placement can make a difference [you may for example have different object files product "data" that goes into different sections of memory in some embedded system], the compiler won't be able to just throw it in any place it likes - that could be somewhere you don't want it.