What makes a singleton thread-unsafe? - c++

I read somewhere that a singleton was thread-unsafe. I'm trying to understand why this is. If I have a singleton object like this:
class singleton final
{
public:
static singleton& instance()
{
static singleton unique;
return unique;
}
private:
singleton() = default;
singleton(singleton const&) = delete;
singleton& operator=(singleton const&) = delete;
};
And if I have code like this:
singleton *p1, *p2;
auto t1 = std::thread([] { p1 = &singleton::instance(); });
auto t2 = std::thread([] { p2 = &singleton::instance(); });
t1.join();
t2.join();
Is it possible for p1 and p2 to point to two different singleton instances? If unique is static, does its "static" nature not take affect until it's fully initialized? If that's so, does that mean that a static object's initialization can be accessed concurrently and thus allowing the creation of multiple static objects?

In C++98/03 a file local static:
X& instance()
{
static X x;
return x;
}
meant that your code would do something like this:
bool __instance_initialized = false;
alignas(X) char __buf_instance[sizeof(X)];
// ...
X& instance()
{
if (!__instance_initialized)
{
::new(__buf_instance) X;
__instance_initialized = true;
}
return *static_cast<X*>(__buf_instance);
}
Where the "__"-prefixed names are compiler supplied.
But in the above code, nothing is stopping two threads from entering the if at the same time, and both trying to construct the X at the same time. The compiler might try to combat that problem by writing:
bool __instance_initialized = false;
alignas(X) char __buf_instance[sizeof(X)];
// ...
X& instance()
{
if (!__instance_initialized)
{
__instance_initialized = true;
::new(__buf_instance) X;
}
return *static_cast<X*>(__buf_instance);
}
But now it is possible for one thread to set __instance_initialized to true and start constructing the X, and have the second thread test and skip over the if while the first thread is still busy constructing X. The second thread would then present uninitialized memory to its client until the first thread finally completes the construction.
In C++11 the language rules were changed such that the compiler must set up the code such that the second thread can not run past, nor start the construction of X until the first thread successfully finishes the construction. This may mean that the second thread has to wait an arbitrary amount of time before it can proceed ... until the first thread finishes. If the first thread throws an exception while trying to construct X, the second thread will wake up and try its hand at constructing it.
Here is the Itanium ABI specification for how the compiler might accomplish that.

Related

C++11 shared_ptr released multiple times under multithreading

Under g++ 4.8.5 compiling, it is found that improper use of sharedptr will cause multiple destruction of shared_ptr.
Fake code:
#include<memory>
class Demo
{
public:
~Demo()
{
// Do something and cost some milliseconds
}
};
typedef std::shared_ptr<Demo> DemoPtr;
DemoPtr global_demo;
DemoPtr instance() {return global_demo;}
// Main thread
int main()
{
global_demo = std::make_shared<Demo>();
// Do something
}
// Thread A
void thread_func()
{
// Do something
if(instance() != nullptr)
{
// Do something
}
// Do something
}
When the main thread ends, the global_demo reference count is reduced to 0, and global_demo begins to be destructed. When global_demo is being destructed, thread A calls instance() and makes a judgment, which causes the reference count of global_demo to increase by one again, and then when the local variable is released, the reference count is reduced to 0 again, resulting in the destruction of the object pointed to by global_demo The function is called again.
View gcc source code:
//*************__shared_count***************//
__shared_count&
operator=(const __shared_count& __r) noexcept
{
_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
if (__tmp != _M_pi)
{
if (__tmp != 0)
__tmp->_M_add_ref_copy();
if (_M_pi != 0)
_M_pi->_M_release();
_M_pi = __tmp;
}
return *this;
}
//************_Sp_counted_base*****************//
void
_M_add_ref_copy()
{ __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
So, this is a GCC bug?
Should I use std::weak_ptr to solve this problem in this case?
So, my instance() method code like this?
DemoPtr instance()
{
std::weak_ptr<Demo> w(global_demo);
if(!w.expired())
{
return w.lock();
}
return nullptr;
}
So, this is a GCC bug?
No. It is a bug in the program:
global_demo is being destructed
thread A calls instance()
DemoPtr instance() {return global_demo;}
You are making a copy (return global_demo;) of an object whose lifetime has ended (is being destructed). The behaviour of the program is undefined.
Should I use std::weak_ptr to solve this problem in this case?
This would not fix the bug. What you must do is join any threads that depend on static variables before returning from main. It may technically be OK to join a thread after main has returned, within a destructor of a static object as long as that object is guaranteed to be destroyed before the depended static object. But good luck with that.
for some threads I cannot control the end.
Then you must avoid using any static variables in those threads. In the example case, create a thread local copy of global_demo, and use that within the thread instead.

Safely moving objects that run a lambda in a member thread that accesses other members

I have a class that has an std::thread member variable which runs a lambda function that depends on some other member variable.
Let me give an example:
struct C {
C() {
thread_ = std::thread([this]() {
running_ = true;
while (running_) {
...
}
});
}
C(C&& rv) {
swap(rv);
}
void swap(C& rhs) {
std::swap(thread_, rhs.thread_); // step 1
std::swap(running_, rhs.running_); // step 2
}
std::thread thread_;
bool running_;
};
int main() {
C c;
C c2 = move(c); // Is c safely moved to c2?
}
What is a safe way to move such an object?
To which object is capture [this] going to point after the move operation.
Which object's running_ is accessed in the lambda's while loop after step 1 but before step 2?
While a std::thread is certainly movable, doing so does not magically revise any pointer referring to it, or its containing object, if any.
Thus, even after you move a C, the thread managed by the contained std::thread will still refer to the objects it referred to before.
So, if you want to safely move/swap a C, use the pimpl-idiom:
Only safe a pointer to the resources the thread might access, and give that pointer to it.
In your case, that means:
Move running_:
struct inner {
std::atomic<bool> running;
};
unique_ptr<inner> data_ = new inner;
Pass the pointed-to data:
auto data = &*data_;
thread_ = std::thread([data]() {
data->running = true;
while (data->running) {
...
}
});
(Optionally also move the data not accessed by the thread.)
Also, even if you didn't ask, your running must be a std::atomic<bool> so the check works.

Singleton multithread code in C++

I have a doubt related to Singleton and multithread programming in C++
Following you can see an example code of a Singleton class with a variable named shared.
I create 1000 threads that modify (+1) that variable of my Singleton global instance. The final value of shared is 1000 but I would expect this value to be under 1000 since I am not protecting this variable for concurrency.
Is the code really thread safe because the class is Singleton or it just happened to be lucky and the value is 1000 but it can perfectly be less than 1000?
#include <iostream>
using namespace std;
class Singleton {
private:
Singleton() {shared = 0;};
static Singleton * _instance;
int shared;
public:
static Singleton* Instance();
void increaseShared () { shared++; };
int getSharedValue () { return shared; };
};
// Global static pointer used to ensure a single instance of the class.
Singleton* Singleton::_instance = NULL;
Singleton * Singleton::Instance() {
if (!_instance) {
_instance = new Singleton;
}
return _instance;
}
void * myThreadCode (void * param) {
Singleton * theInstance;
theInstance = Singleton::Instance();
theInstance->increaseShared();
return NULL;
}
int main(int argc, const char * argv[]) {
pthread_t threads[1000];
Singleton * theInstance = Singleton::Instance();
for (int i=0; i<1000; i++) {
pthread_create(&threads[i], NULL, &myThreadCode, NULL);
}
cout << "The shared value is: " << theInstance->getSharedValue() << endl;
return 0;
}
Is the code really thread safe because the class is Singleton or it just happened to be lucky and the value is 1000 but it can perfectly be less than 1000?
You got lucky...
In reality, the most likely issue with what you're observing has to-do with the fact that the time it takes to increment the value of your singleton on your specific machine is less than the time it takes the operating system to allocate the resources to launch an individual pthread. Thus you never ended up with a scenario where two threads contend for the unprotected resources of the singleton.
A much better test would have been to launch all of your pthreads first, have them block on a barrier or condition variable, and then perform the increment on the singleton once the barrier's condition of all the threads being "active" is met ... at that point you would have been much more likely to have seen the sorts of data-races that occur with non-atomic operations like an increment operation.
If you implement your Singleton like this, the singleton creation will be thread safe:
Singleton & Singleton::Instance() {
static Singleton instance;
return instance;
}
Since the instance can never be null, and no memory to manager, a reference is returned instead of a pointer.
The increment operation can be made atomic by using platform specific operations (g++ provides built-ins, e.g. __sync_fetch_and_add), or C++11 atomic from STL, or Boost.Atomic, or with mutex guards.
std::atomic<int> shared;
void increaseShared () { ++shared; };

std::thread : how to declare a thread in class body as a normal member?

I want to have a thread for each instance of Page object. At a time only one of them can execute (simply checks if pointer to current running thread is joinable or not..)
class Page : public std::vector<Step>
{
// ....
void play();
void start(); // check if no other thread is running. if there is a running thread, return. else join starter
std::thread starter; // std::thread running this->play()
static std::thread* current; // pointer to current running thread
// ...
};
I want to be able to fire-up starter threads of Page objects. for example like this:
Page x , y , z;
// do some stuff for initialize pages..
x.start();
// do some other work
y.start(); // if x is finished, start y otherwise do nothing
// do some other lengthy work
z.start(); // if x and y are not running, start z
I can't manage to declare started as a member of Page. I found that it's because of the fact std::threads can only initialized at declaration time. (or something like that, cause it's not possible to copy a thread)
void x()
{
}
//...
std::thread t(x); // this is ok
std::thread r; // this is wrong, but I need this !
r = std::thread(this->y); // no hope
r = std::thread(y); // this is wrong too
You can initialize the thread to the function to run by using a member initializer list. For example, consider this constructor for Page:
class Page {
public:
Page(); // For example
private:
std::thread toRun;
};
Page::Page() : toRun(/* function to run */) {
/* ... */
}
Notice how we use the initialization list inside the Page constructor to initialize toRun to the function that ought to be run. This way, toRun is initialized as if you had declared it as a local variable
std::string toRun(/* function to run */);
That said, there are two major problems I think that you must address in your code. First, you should not inherit from std::vector or any of the standard collections classes. Those classes don't have their destructors marked virtual, which means that you can easily invoke undefined behavior if you try to treat your Page as a std::vector. Instead, consider making Page hold a std::vector as a direct subobject. Also, you should not expose the std::thread member of the class. Data members should, as a general rule, be private to increase encapsulation, make it easier to modify the class in the future, and prevent people from breaking all of your class's invariants.
Hope this helps!
Never publicly inherit from a std container, unless the code is meant to be throw away code. An honestly it's terrifying how often throw away code becomes production code when push comes to shove.
I understand you don't want to reproduce the whole std::vector interface. That is tedious write, a pain to maintain, and honestly could create bugs.
Try this instead
class Page: private std::vector
{
public:
using std::vector::push_back;
using std::vector::size;
// ...
};
Ignoring the std::vector issue this should work for the concurrency part of the problem.
class Page
{
~Page( void )
{
m_thread.join();
}
void start( void );
private:
// note this is private, it must be to maintain the s_running invariant
void play( void )
{
assert( s_current == this );
// Only one Page at a time will execute this code.
std::lock_guard<std::mutex> _{ s_mutex };
s_running = nullptr;
}
std::thread m_thread;
static Page* s_running;
static std::mutex s_mutex;
};
Page* Page::s_running = nullptr;
std::mutex Page::s_mutex;
std::condition Page::s_condition;
void Page::start( void )
{
std::lock_guard<std::mutex> _{ s_mutex };
if( s_running == nullptr )
{
s_running = this;
m_thread = std::thread{ [this](){ this->play(); } };
}
}
This solution is may have initialization order issues if Page is instantiate before main()

Double checked locking on C++: new to a temp pointer, then assign it to instance

Anything wrong with the following Singleton implementation?
Foo& Instance() {
if (foo) {
return *foo;
}
else {
scoped_lock lock(mutex);
if (foo) {
return *foo;
}
else {
// Don't do foo = new Foo;
// because that line *may* be a 2-step
// process comprising (not necessarily in order)
// 1) allocating memory, and
// 2) actually constructing foo at that mem location.
// If 1) happens before 2) and another thread
// checks the foo pointer just before 2) happens, that
// thread will see that foo is non-null, and may assume
// that it is already pointing to a a valid object.
//
// So, to fix the above problem, what about doing the following?
Foo* p = new Foo;
foo = p; // Assuming no compiler optimisation, can pointer
// assignment be safely assumed to be atomic?
// If so, on compilers that you know of, are there ways to
// suppress optimisation for this line so that the compiler
// doesn't optimise it back to foo = new Foo;?
}
}
return *foo;
}
No, you cannot even assume that foo = p; is atomic. It's possible that it might load 16 bits of a 32-bit pointer, then be swapped out before loading the rest.
If another thread sneaks in at that point and calls Instance(), you're toasted because your foo pointer is invalid.
For true security, you will have to protect the entire test-and-set mechanism, even though that means using mutexes even after the pointer is built. In other words (and I'm assuming that scoped_lock() will release the lock when it goes out of scope here (I have little experience with Boost)), something like:
Foo& Instance() {
scoped_lock lock(mutex);
if (foo != 0)
foo = new Foo();
return *foo;
}
If you don't want a mutex (for performance reasons, presumably), an option I've used in the past is to build all singletons before threading starts.
In other words, assuming you have that control (you may not), simply create an instance of each singleton in main before kicking off the other threads. Then don't use a mutex at all. You won't have threading problems at that point and you can just use the canonical don't-care-about-threads-at-all version:
Foo& Instance() {
if (foo != 0)
foo = new Foo();
return *foo;
}
And, yes, this does make your code more dangerous to people who couldn't be bothered to read your API docs but (IMNSHO) they deserve everything they get :-)
Why not keep it simple?
Foo& Instance()
{
scoped_lock lock(mutex);
static Foo instance;
return instance;
}
Edit: In C++11 where threads is introduced into the language. The following is thread safe. The language guarantees that instance is only initialized once and in a thread safe manor.
Foo& Instance()
{
static Foo instance;
return instance;
}
So its lazily evaluated. Its thread safe. Its very simple. Win/Win/Win.
This depends on what threading library you're using. If you're using C++0x you can use atomic compare-and-swap operations and write barriers to guarantee that double-checked locking works. If you're working with POSIX threads or Windows threads, you can probably find a way to do it. The bigger question is why? Singletons, it turns out, are usually unnecessary.
the new operator in c++ always invovle 2-steps process :
1.) allocating memory identical to simple malloc
2.) invoke constructor for given data type
Foo* p = new Foo;
foo = p;
the code above will make the singleton creation into 3 step, which is even vulnerable to problem you trying to solve.
Why don't you just use a real mutex ensuring that only one thread will attempt to create foo?
Foo& Instance() {
if (!foo) {
pthread_mutex_lock(&lock);
if (!foo) {
Foo *p = new Foo;
foo = p;
}
pthread_mutex_unlock(&lock);
}
return *foo;
}
This is a test-and-test-and-set lock with free readers. Replace the above with a reader-writer lock if you want reads to be guaranteed safe in a non-atomic-replacement environment.
edit: if you really want free readers, you can write foo first, and then write a flag variable fooCreated = 1. Checking fooCreated != 0 is safe; if fooCreated != 0, then foo is initialized.
Foo& Instance() {
if (!fooCreated) {
pthread_mutex_lock(&lock);
if (!fooCreated) {
foo = new Foo;
fooCreated = 1;
}
pthread_mutex_unlock(&lock);
}
return *foo;
}
It has nothing wrong with your code. After the scoped_lock, there will be only one thread in that section, so the first thread that enters will initialize foo and return, and then second thread(if any) enters, it will return immediately because foo is not null anymore.
EDIT: Pasted the simplified code.
Foo& Instance() {
if (!foo) {
scoped_lock lock(mutex);
// only one thread can enter here
if (!foo)
foo = new Foo;
}
return *foo;
}
Thanks for all your input. After consulting Joe Duffy's excellent book, "Concurrent Programming on Windows", I am now thinking that I should be using the code below. It's largely the code from his book, except for some renames and the InterlockedXXX line. The following implementation uses:
volatile keyword on both the temp and "actual" pointers to protect against re-ordering from the compiler.
InterlockedCompareExchangePointer to protect against reordering from
the CPU.
So, that should be pretty safe (... right?):
template <typename T>
class LazyInit {
public:
typedef T* (*Factory)();
LazyInit(Factory f = 0)
: factory_(f)
, singleton_(0)
{
::InitializeCriticalSection(&cs_);
}
T& get() {
if (!singleton_) {
::EnterCriticalSection(&cs_);
if (!singleton_) {
T* volatile p = factory_();
// Joe uses _WriterBarrier(); then singleton_ = p;
// But I thought better to make singleton_ = p atomic (as I understand,
// on Windows, pointer assignments are atomic ONLY if they are aligned)
// In addition, the MSDN docs say that InterlockedCompareExchangePointer
// sets up a full memory barrier.
::InterlockedCompareExchangePointer((PVOID volatile*)&singleton_, p, 0);
}
::LeaveCriticalSection(&cs_);
}
#if SUPPORT_IA64
_ReadBarrier();
#endif
return *singleton_;
}
virtual ~LazyInit() {
::DeleteCriticalSection(&cs_);
}
private:
CRITICAL_SECTION cs_;
Factory factory_;
T* volatile singleton_;
};