My aim is to keep an std::thread object as data member, and initialize it when needed.
I'm not able to do this (as in my code below) because the copy constructor of the std::thread class is deleted. Is there any other way to do it?
class MyClass
{
public:
MyClass():DiskJobThread(){};
~MyClass();
void DoDiskJobThread();
private:
int CopyThread(const std::wstring & Source, const std::wstring & Target);
int MoveThread(const std::wstring & Source, const std::wstring & Target);
std::thread DiskJobThread;
};
MyClass::~MyClass()
{
DiskJobThread.join();
}
void MyClass::DoDiskJobThread()
{
std::wstring Source = GetSource();
std::wstring Target = GetTarget();
int m_OperationType = GetOperationType();
if (m_OperationType == OPERATION_COPY)
{
DiskJobThread = std::thread(&MyClass::CopyThread, *this, Source, Target);
}
else if (m_OperationType == OPERATION_MOVE)
{
DiskJobThread = std::thread(&MyClass::MoveThread, *this, Source, Target);
}
}
How about wrapping it in a pointer?
std::unique_ptr<std::thread> thread_ptr;
// Look into std::make_unique if possible
thread_ptr = std::unique_ptr<std::thread>(new std::thread(...));
Edit: And yes, the others have mentioned it and I didn't feel the need to add it here, but in order to avoid more downvote piling, I'll say it: You are passing *this and not this thereby copying an instance of your class. (Problems arise because it's non-copyable. Pass this and you should be good to go.)
Your problem is something else - you're passing an instance of MyClass into the thread instead of the pointer to MyClass which the member functions expect. Simply change DoDiskJobThread() like this (do not dereference this):
void MyClass::DoDiskJobThread()
{
std::wstring Source = GetSource();
std::wstring Target = GetTarget();
int m_OperationType = GetOperationType();
if (m_OperationType == OPERATION_COPY)
{
DiskJobThread = std::thread(&MyClass::CopyThread, this, Source, Target);
}
else if (m_OperationType == OPERATION_MOVE)
{
DiskJobThread = std::thread(&MyClass::MoveThread, this, Source, Target);
}
}
You were getting the error because *this resulted in trying to copy MyClass into the thread function, and the copy ctor of your class is deleted (because that of std::thread is deleted). However, the member functions CopyThread and MoveThread require a pointer as the first (hidden) argument anyway.
Live demonstration
You can't initialize the thread object after it's created; by definition, initialization occurs when an object is created. But you can use swap to move a thread object into another:
std::thread thr1; // no thread of execution
std::thread thr2(my_function_object); // creates thread of execution
thr1.swap(thr2); // thr1 is now running the thread created as thr2
// and thr2 has no thread of execution
My aim is to keep an std::thread object as data member, and initialize it when needed.
Since a default-constructed std::thread object doesn't have an associated thread of execution, you can achieve that by using such an object as the target for a (move) assignment operation. However, note that the following is not initialization, but assignment:
std::thread th; // no thread of execution associated with th object
// ...
th = std::thread(func);
The temporary std::thread object created with std::thread(func) has an associated thread of execution. The ownership of this thread of execution is transferred to th through the move assignment – i.e., th steals the ownership of that thread of execution from the temporary.
Note that if th had an associated thread of execution at the moment of the assignment, std::terminate() would have been called.
Related
I would like to create a object in which I can start a thread and have a function to join withe the created thread. Everything insight the object, so that the thread is a private component of the object.
I have tried a bit and got those Results. Could some of you explain me what I have done wrong, and why I get this errors?
A.h
#include <thread>
class A{
std::thread a;
public:
//this should be a void function
std::thread startThread();
void join();
void (*threadFunction)() = nullptr;
};
and the A.cpp
#include "../header/A.h"
std::thread A::startThread()
{
std::thread a((*threadFunction));
return a;
}
void A::join()
{
a.join();
}
main.cpp
void newFunc(){
std::cout<<"I'm a thread"<<std::endl;
}
int main(){
auto object = new A();
object->threadFunction = &newFunc;
//Version 1) Error "terminate called without an active exception"
object->startThread();
object->join();
/*
Version 2) terminate called after throwing an instance of 'std::system_error'
I'm a thread
what(): Invalid argument
*/
auto value = object->startThread();
object->join();
//Version 3) I'm a thread
auto value = object->startThread();
value.join();
}
I don't see the difference. I have stored the thread in the object, so it is not lost... and when I store the return value and don't use it, its almost fine... but not really ... and directly join() is perfect ... I don't get it :D
Please help me
std::thread A::startThread()
{
std::thread a((*threadFunction));
return a;
}
Does not interact with the member variable a, but it creates a new local variable std::thread object and then moves it to the result (unless the move is optimized out). The thread A::a always remains the default constructed one. A default constructed thread object is non-joinable, i.e. throws an exception on the call of std::thread::join. The only thread join can be called for without causing an exception is the thread object returned from the function.
If you don't join the returned thread and its destructor runs (happens when you drop the temporary thread object returned (Version 1)), std::terminate shuts your program down.
To make this work you need to move assign a newly created thread to the member variable and not return the thread object or just return a reference to it:
void A::startThread()
{
a = std::thread(threadFunction);
}
or
std::thread& A::startThread()
{
a = std::thread(threadFunction);
return a;
}
I wouldn't recommend the second alternative, it drastically reduces your ability to enforce class invariants with regards to the thread lifecycle.
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.
I'm trying to come up with a fast way of solving the following problem:
I have a thread which produces data, and several threads which consume it. I don't need to queue produced data, because data is produced much more slowly than it is consumed (and even if this failed to be the case occasionally, it wouldn't be a problem if a data point were skipped occasionally). So, basically, I have an object that encapsulates the "most recent state", which only the producer thread is allowed to update.
My strategy is as follows (please let me know if I'm completely off my rocker):
I've created three classes for this example: Thing (the actual state object), SharedObject<Thing> (an object that can be local to each thread, and gives that thread access to the underlying Thing), and SharedObjectManager<Thing>, which wraps up a shared_ptr along with a mutex.
The instance of the SharedObjectManager (SOM) is a global variable.
When the producer starts, it instantiates a Thing, and tells the global SOM about it. It then makes a copy, and does all of it's updating work on that copy. When it is ready to commit it's changes to the Thing, it passes the new Thing to the global SOM, which locks it's mutex, updates the shared pointer it keeps, and then releases the lock.
Meanwhile, the consumer threads all intsantiate SharedObject<Thing>. these objects each keep a pointer to the global SOM, as well as a cached copy of the shared_ptr kept by the SOM... It keeps this cached until update() is explicitly called.
I believe this is getting hard to follow, so here's some code:
#include <mutex>
#include <iostream>
#include <memory>
class Thing
{
private:
int _some_member = 10;
public:
int some_member() const { return _some_member; }
void some_member(int val) {_some_member = val; }
};
// one global instance
template<typename T>
class SharedObjectManager
{
private:
std::shared_ptr<T> objPtr;
std::mutex objLock;
public:
std::shared_ptr<T> get_sptr()
{
std::lock_guard<std::mutex> lck(objLock);
return objPtr;
}
void commit_new_object(std::shared_ptr<T> new_object)
{
std::lock_guard<std::mutex> lck (objLock);
objPtr = new_object;
}
};
// one instance per consumer thread.
template<typename T>
class SharedObject
{
private:
SharedObjectManager<T> * som;
std::shared_ptr<T> cache;
public:
SharedObject(SharedObjectManager<T> * backend) : som(backend)
{update();}
void update()
{
cache = som->get_sptr();
}
T & operator *()
{
return *cache;
}
T * operator->()
{
return cache.get();
}
};
// no actual threads in this test, just a quick sanity check.
SharedObjectManager<Thing> glbSOM;
int main(void)
{
glbSOM.commit_new_object(std::make_shared<Thing>());
SharedObject<Thing> myobj(&glbSOM);
std::cout<<myobj->some_member()<<std::endl;
// prints "10".
}
The idea for use by the producer thread is:
// initialization - on startup
auto firstStateObj = std::make_shared<Thing>();
glbSOM.commit_new_object(firstStateObj);
// main loop
while (1)
{
// invoke copy constructor to copy the current live Thing object
auto nextState = std::make_shared<Thing>(*(glbSOM.get_sptr()));
// do stuff to nextState, gradually filling out it's new value
// based on incoming data from other sources, etc.
...
// commit the changes to the shared memory location
glbSOM.commit_new_object(nextState);
}
The use by consumers would be:
SharedObject<Thing> thing(&glbSOM);
while(1)
{
// think about the data contained in thing, and act accordingly...
doStuffWith(thing->some_member());
// re-cache the thing
thing.update();
}
Thanks!
That is way overengineered. Instead, I'd suggest to do following:
Create a pointer to Thing* theThing together with protection mutex. Either a global one, or shared by some other means. Initialize it to nullptr.
In your producer: use two local objects of Thing type - Thing thingOne and Thing thingTwo (remember, thingOne is no better than thingTwo, but one is called thingOne for a reason, but this is a thing thing. Watch out for cats.). Start with populating thingOne. When done, lock the mutex, copy thingOne address to theThing, unlock the mutex. Start populating thingTwo. When done, see above. Repeat untill killed.
In every listener: (make sure the pointer is not nullptr). Lock the mutex. Make a copy of the object pointed two by the theThing. Unlock the mutex. Work with your copy. Burn after reading. Repeat untill killed.
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.
I need to make own simple thread-safe shared pointer class for embedded devices.
I made counting master pointer and handle as described in Jeff Alger's book (C++ for real programmers). This is my sources:
template <class T>
class counting_ptr {
public:
counting_ptr() : m_pointee(new T), m_counter(0) {}
counting_ptr(const counting_ptr<T>& sptr) :m_pointee(new T(*(sptr.m_pointee))), m_counter(0) {}
~counting_ptr() {delete m_pointee;}
counting_ptr<T>& operator=(const counting_ptr<T>& sptr)
{
if (this == &sptr) return *this;
delete m_pointee;
m_pointee = new T(*(sptr.m_pointee));
return *this;
}
void grab() {m_counter++;}
void release()
{
if (m_counter > 0) m_counter--;
if (m_counter <= 0)
delete this;
}
T* operator->() const {return m_pointee;}
private:
T* m_pointee;
int m_counter;
};
template <class T>
class shared_ptr {
private:
counting_ptr<T>* m_pointee;
public:
shared_ptr() : m_pointee(new counting_ptr<T>()) { m_pointee->grab(); }
shared_ptr(counting_ptr<T>* a_pointee) : m_pointee(a_ptr) { m_pointee->grab(); }
shared_ptr(const shared_ptr<T>& a_src) : m_pointee(a_src.m_pointee) {m_pointee->grab(); }
~shared_ptr() { m_pointee->release(); }
shared_ptr<T>& operator=(const shared_ptr<T>& a_src)
{
if (this == &a_src) return *this;
if (m_pointee == a_src.m_pointee) return *this;
m_pointee->release();
m_pointee = a_src.m_pointee;
m_pointee->grab();
return *this;
}
counting_ptr<T>* operator->() const {return m_pointee;}
};
This works fine if it used in one thread. Suppose I have two threads:
//thread 1
shared_ptr<T> p = some_global_shared_ptr;
//thread 2
some_global_shared_ptr = another_shared_ptr;
This case I can get undefined behaviour if one of threads will be interrupted between memory allocating/deallocating and counter changing. Of course I can enclose shared_ptr::release() into critical section so deletion of the pointer can be made safety. But what can I do with copy constructor? It is possible that constructor will be interrupted during m_pointee construction by another thread which will delete this m_pointee.
The only way I see to make shared_ptr assignement thread-safe is to enclose the assignment (or creation) into critical section. But this must be done in "user code". In other words user of shared_ptr class must take care about safety.
Is it possible to change this realization somehow to make the shared_ptr class thread safe?
=== EDIT ===
After some investigations (thanks to Jonathan) I realized that my shared_ptr has three unsafe places:
Unatomic counter changing
Unatomic assignment operator (source object can be deleted during copying)
shared_ptr copy constructor (very similar to previous case)
First two cases could be easily fixed by adding crtical sections. But I can't realize how to add critical section into copy constructor? Copy of a_src.m_pointee created before any other code in the constructor executed and can be deleted before calling grab. As Jonathan said in his comment it is very difficult to fix this problem.
I made such test:
typedef shared_ptr<....> Ptr;
Ptr p1, p2;
//thread 1
while (true)
{
Ptr p;
p2 = p;
}
//thread 2
while (!stop)
{
p1 = p2;
Ptr P(p2);
}
Of course, it crashed. But I have tried to use std::shared_ptr in VS 2013 C++. And it works!
So it is possible to make thread-safe copy constructor for shared_ptr. But stl sources too difficult for me and I don't understand how they did the trick. Please anyone explain me how it works in STL?
=== EDIT 2 ===
I am sorry, but the test for std::shared_ptr was made wrong. It doesn't pass too exactly as boost::shared_ptr does. Sometimes copy constructor fails to make a copy because source was deleted during copying. In this case empty pointer will be created.
This is hard to get right, I would seriously consider whether you actually need to support concurrent reads and writes of a single object (boost::shared_ptr and std::shared_ptr do not support that unless all accesses are done through the atomic_xxx() functions that are overloaded for shared_ptr and which typically acquire a lock).
For a start you would need to change shared_ptr<T>::m_pointee to atomic<counting_ptr<T>*> so that you can store a new value in it atomically. counting_ptr<T>::m_counter would need to be atomic<int> so the ref-count updates can be done atomically.
Your assignment operator is a big problem, you would need to at least re-order the operations so you increase the ref-count first, and avoid time of check to time of use bugs, something like this (not even compiled, let alone tested):
shared_ptr<T>& operator=(const shared_ptr<T>& a_src)
{
counter_ptr<T>* new_ptr = a_src.m_pointee.load();
new_ptr->grab();
counter_ptr<T>* old_ptr = m_pointee.exchange(new_ptr);
old_ptr->release();
return *this;
}
This form is safe against self-assignment (it just increases the ref-count then decreases it again if the two objects share the same pointee). It's still not safe against a_src changing while you try to copy it. Consider the case where a_src.m_pointee->m_counter == 1 initially. The current thread could call load() to get the other object's pointer, then a second thread could call release() on that pointer, which would delete it, making the grab() call undefined behaviour because it accesses an object that has been destroyed and memory that has been deallocated. Fixing that requires a pretty major redesign and maybe atomic operations that can operate on two words at once.
Getting this right is possible but is hard and you should really reconsider whether it's necessary, or if the code using it can just avoid modifying objects while other threads are reading them, except while the user has locked a mutex or other form of manual synchronisation.
After some investigations I can conclude that it is impossible to make thread-safe shared_ptr class where thread-safety understood as follow:
//thread 1
shared_ptr<T> p = some_global_shared_ptr;
//thread 2
some_global_shared_ptr = another_shared_ptr;
This example doesn't guarantees that p in first thread will point to old or new value of some_global_shared_ptr. In general this example leads to undefined behavior. The only way to make the example safety is to wrap both operators into critical sections or mutial exclusions.
The main problem caused by copy constructor of shared_ptr class. Other problems could be solved using critical sections inside shared_ptr methods.
Just inherit your class from CmyLock and you can make everything thread safe.
I use this class already many years in all my code, usually combined with class CmyThread, which creates a thread that has a very safe mutex. Maybe my answer is a little late, but above answers are not good practice.
/** Constructor */
CmyLock::CmyLock()
{
(void) pthread_mutexattr_init( &m_attr);
pthread_mutexattr_settype( &m_attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init( &m_mutex, &m_attr);
}
/** Lock the thread for other threads. */
void CmyLock::lock()
{
pthread_mutex_lock( &m_mutex);
}
/** Unlock the thread for other threads. */
void CmyLock::unlock()
{
pthread_mutex_unlock( &m_mutex);
}
Here also the thread class. Try Please copy CmyLock and CmyThread classes to your project and tell when it's working! Although it's made for Linux, also Windows and Mac should be able to run this.
For the include file:
// #brief Class to create a single thread.
class CmyThread : public CmyLock
{
friend void *mythread_interrupt(void *ptr);
public:
CmyThread();
virtual ~CmyThread();
virtual void startWorking() {}
virtual void stopWorking() {}
virtual void work();
virtual void start();
virtual void stop();
bool isStopping() { return m_stopThread; }
bool isRunning() { return m_running && !m_stopThread; }
private:
virtual void run();
private:
bool m_running; ///< Thread is now running.
pthread_t m_thread; ///< Pointer to thread.
bool m_stopThread; ///< Indicate to stop thread.
};
The C++ file:
/** #brief Interrupt handler.
* #param ptr [in] SELF pointer for the instance.
*/
void *mythread_interrupt(void *ptr)
{
CmyThread *irq =
static_cast<CmyThread*> (ptr);
if (irq != NULL)
{
irq->run();
}
return NULL;
}
/** Constructor new thread. */
CmyThread::CmyThread()
: m_running( false)
, m_thread( 0)
, m_stopThread( false)
{
}
/** Start thread. */
void CmyThread::start()
{
m_running =true;
m_stopThread =false;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
int stack_size =8192*1024;
pthread_attr_setstacksize(&attr, stack_size);
pthread_create(&m_thread, &attr, mythread_interrupt, (void*) this);
}
/** Thread function running. */
void CmyThread::run()
{
startWorking();
while (m_running && m_stopThread==false)
{
work();
}
m_running =false;
stopWorking();
pthread_exit(0);
}
/** Function to override for a thread. */
virtual void CmyThread::work()
{
delay(5000);
}
For example, here a simplistic example to store and retrieve 1000 data:
class a : public CmyLock
{
set_safe(int *data)
{
lock();
fileContent =std::make_shared<string>(data);
unlock();
}
get_safe(char *data)
{
lock();
strcpy( data, fileContent->c_str());
unlock();
}
std::shared_ptr<string> fileContent;
};