My problem deals with the usage of different vectors at the same time. I know I can't expect the same vector to work in multiple threads simultaneously. I've broken down the program so it is easier to understand it. I have a ThreadClass class that has a constructor which just adds an element to the vector k and then calls a thread toCall which then outputs the size of the vector which is supposed to be one. The object of this class is created inside of a different vector inside of the main() function using vector's push_back member.
The output turns out to be 0. Sometimes I can get 1 as well. I can produce more of the number 1 if I switch to debug mode. I have tested this problem on a gnu C++17 compiler (Ubuntu 16.04) and a Visual Studio compiler (Windows 10). My question is now if this example shows that I should avoid using vectors in multi-threaded programs totally?
class ThreadClass
{
private:
std::vector<int> k;
std::thread thr;
public:
ThreadClass() {
k.push_back(27);
thr = std::thread(&ThreadClass::toCall, this);
}
void toCall() {
std::cout << k.size() << std::endl;
}
void close() {
if (thr.joinable())thr.join();
}
};
int main(){
std::vector<ThreadClass> lols;
lols.push_back(ThreadClass());
lols[0].close();
return 0;
}
The problem is that a value of type ThreadClass holds a reference to itself. Specifically, thr contains a copy of this.
When you copy or move such a value, e.g. when the temporary ThreadClass() is moved into lols, the duplicate holds a duplicate this ptr, i.e. it points to the old temporary, whose lifetime ends after the call to lols.push_back finishes.
We can replicate this problem without threads:
class Foo
{
private:
std::vector<int> k;
Foo* possibly_this;
public:
Foo() {
k.push_back(27);
possibly_this = this;
}
void toCall() {
std::cout << possibly_this->k.size() << std::endl;
}
};
int main(){
std::vector<Foo> lols;
lols.push_back(Foo{});
lols[0].toCall();
}
(For me, it prints 0 with -O0 on 7.3.1, but again, it's UB, so it could do anything on your machine.)
lols.emplace() will not help. If a std::vector resizes, then all pointers/iterators into it are invalidated. Unfortunately, you can't change the pointers stored in thr, so you're left with one solution: disable ThreadClass's copy and move constructors, like so:
//within the definition of ThreadClass
ThreadClass(ThreadClass const&) = delete;
In order to place ThreadClass in a container, you will need an additional level of indirection to allow the actual object of a value of type ThreadClass to have a stable location. Either std::list<ThreadClass> or std::vector<std::unique_ptr<ThreadClass>> will do the trick.
One issue is that your thread can call toCall before the constructor returns. It's not a good idea to go creating threads that call back into the object in the constructor. Defer the thread creation to some kind of start or launch function and call that after the constructor returns.
This is also a problem:
lols.push_back(ThreadClass());
Here, the destructor (of the temporary) can even run before toCall gets called! That's definitely not going to work. That's another really good reason not to create a thread in a constructor -- it makes temporary objects disastrous.
Related
I have an object that has different constructors. Now I want to add another constructor that based on arbitrary data will try to process that data and call the correct constructor.
AFAIK there are two ways to do it:
static function that returns the created object
static *A from_data(/arbitrary data/);
create a private "init" function that is called by constructors
But I am wondering what are the problems and potential pitfalls of using a placement new on this using the desired constructor. So the code would be:
#include <new>
struct A
{
/*different constructors*/
A(int i) {};
A(double d) {};
A(/*large set of data*/)
{
/*large set of data gets processed and depending on the processing a different constructor gets called*/
this->~A(); //deletes current object
if (true) {
new (this) A(1); //reconstructs object calling the correct constructor for the data
} else {
new (this) A(1.0); //reconstructs object calling the correct constructor for the data
}
};
};
int main(int argc, char* argv[])
{
A a;
}
You want a compile time decision (choice of constructor to delegate to) from run-time information (result of processing a data set).
That means that what you directly want, cannot be done.
But you can use your idea of a static member function that returns the created object, except that instead of A* it should return A, or else a smart pointer.
Re the other suggested solution,
” create a private "init" function that is called by cosntructors
… that doesn't solve the stated problem, and it's a generally bad idea.
Re
” what are the problems and potential pitfalls of using a placement new on this
Well, it's not code you can rely on. I believe it's Undefined Behavior because at the point where the object self-destroys it's not completely initialized. If it should turn out that it's technically well defined for the case at hand, it's not code that you would want to rely on. And in a setting with possible maintenance, someone stumbling on this code would have to replace it rather than wasting time trying to prove UB or not. Just Say No™ to the dark corners of the language.
I briefly considered spending some time trying to figure out whether the shown example results in undefined behavior, or not. But I quickly decided that this is irrelevant, a waste of time, and is completely beside the point because the current C++ standard has a perfectly well-defined, clean mechanism to do exactly the same thing, and it would be more productive to focus my answer on that, instead.
I'm referring to delegating constructors, of course:
class A {
public:
A(int n) {
// whatever
}
A(const char *p, double z)
: A( /* some formula that calculates an int value goes here */ )
{
}
};
The current C++ standard specifies a well-defined way for one constructor to delegate the actual job of constructing and initializing an instance of the class by invoking a different constructor.
Note that this doesn't mean that one constructor gets to execute arbitrary code, before deciding to invoke the delegated-to constructor. The delegation must occur as the very first order of business, where you normally see the initialization section of a constructor; where you see things like the superclasses' constructors, if any.
Only after the delegated-to constructor returns, does the delegated-from constructor have an option of running more code of its own, to finish the job.
But this is just a minor inconvenience, easily addressed with just a little bit of coding:
class A {
public:
A(int n) {
// whatever
}
A(const char *p, double z)
: A(figure_out_an_int_value_from_p_and_z(p, z))
{
}
private:
static int figure_out_an_int_value_from_p_and_z(const char *p, double z)
{
int a_very_complicated_value;
// Some complicated code that computes a_very_complicated_value.
return a_very_complicated_value;
}
};
Let's say I have a member variable vector initialised in the constructor, and this vector is read (not written to anywhere else) in several other member functions. Would I need to protect access to the vector (including in the constructor), or is it guaranteed that the object will be fully initialised and flushed to main memory before it's used in other threads?
Let me provide an example:
class A
{
public:
A();
void f1();
void f2();
private:
std::vector<int> v;
};
A::A()
{
// do some setup work in v
v.push_back(1);
}
// called from thread1
void A::f1()
{
// some readonly work on v
for (auto i : v) {
// do something on i
}
}
// called from thread2
void A::f2()
{
// more readonly work on v
if (v.empty()) {
// do other work
}
}
Do I need to lock-protect v in A::A(), A::f1() and A::f2()?
An object is created by a single thread, so you never have to worry about thread safety when running code inside the constructor that touches member variables. However, if you are using static variables within the constructor then you may need to add some form of locking around the access.
There is an edge case where code within a constructor can be called by multiple threads, and this is when you are using either placement new. For example, let's say you've got a buffer somewhere, and you're going to allocate an object into it:
byte buffer[100];
Foo *foo = new (buffer) Foo;
Here, unless you are locking around the call to new then it's possible for two or more constructors to run in parallel as they're running against the same block of memory. However, this is a real specialized edge-case and would require special handling (eg locking around the placement-new construction).
An object is constructed by a single thread.
Other threads can access the object only by means of the instance reference.
In other words, the object's constructor will have finished its work before other threads call a method.
You therefore don't need to implement thread-safe code within a constructor.
Of course, in case another object is passed to the constructor as a parameter, eventual access to that object within the constructor, should be thread-safe.
As stated in the other answers, there is no point in implementing synchronization primitives in the constructer, but that doesn't mean you can't have a race, if you don't synchronize externally:
std::atomic<A*> g_ptr = nullptr;
void threadFun1() {
g_ptr.store(new A{}, std::memory_order_relaxed);
}
void threadFun2() {
A* l_ptr = nullptr;
while (l_ptr == nullptr) {
l_ptr = g_ptr.load(std::memory_order_relaxed);
}
l_ptr->f1();
}
In above code, you have a data race between the constructor of A and f1. The problem is that - without synchonization - from the point of view of thread2, g_ptr might be written before the object is completely constructed.
However, there is nothing you can do inside the constructor to prevent this kind of race. Instead you have to use external means of synchronization, like using non-relaxed memory ordering for the atomic load and store operations or starting thread2 from within thread1 after the global variable is set.
Take this code example below:
model.h
namespace Stackoverflow {
class Model {
public:
Model();
~Model();
std::vector<int> *integers() const { return _integers.get(); }; // read only
private:
std::unique_ptr<std::vector<int>> _integers; // registered before constructor
};
}
model.cpp
Stackoverflow::Model::Model() {
_integers = std::make_unique<std::vector<int>>(); // initialized
}
Stackoverflow::Model::~Model() {
_integers.release();
}
The private member "_integers" will be registered but not initialized until the constructor is being called by the caller.
Stackoverflow::Model stackoverflow;
When another thread want to access this vector, call the getter.
auto *vector = stackoverflow.integers();
The member will be fully initialized when the caller is actually asking for the vector.
#include <functional>
#include <iostream>
using namespace std;
class test {
public:
test(){ p = new int[10];}
void print_info(double a)
{
cerr << a << endl;
}
~test(){
cerr << __LINE__ << endl;
delete []p;
}
private:
int *p;
};
int main()
{
test t;
std::function<void(void)> f = std::bind(&test::print_info, t, 2.0);
//std::function<void(void)> f = std::bind(&test::print_info, std::cref(t), 2.0);
return 0;
}
It will crash, since test::~test() is called twice. But, if I replace t with std::cref(t) (or std::ref(t), &t), ~test() will be called only once when exiting main().
I didn't figure out the reason. I'm on Ubuntu 12.04 64bit, using gcc 4.6.3.
You're binding a copy of the object t. Since your class tries to manage dynamic memory, but doesn't follow the Rule of Three, it has invalid copy semantics - both copies will try to delete the same dynamic array on destruction.
If you used a class like std::vector, with valid copy semantics, to manage the dynamic array, then all would be fine.
Since you are binding a copy of object t, not t itself, that will be destructed when returning from bind object will be destructed and since you don't overload copy c-tor, default copy c-tor will make shallow copy and your p will be deleted twice. For binding t itself you should use std::ref.
std::function<void(void)> f = std::bind(&test::print_info, t, 2.0);
It will crash, since test::~test() is called twice. But, if I replace t with std::cref(t) (or std::ref(t), &t), ~test() will be called only once when exiting main().
I didn't figure out the reason. I'm on Ubuntu 12.04 64bit, using gcc 4.6.3.
The reason is actually quite simple, the std::bind function creates a functor object that holds a copy of the arguments. In your program there is a bug and copying objects of the type end up with two objects having pointers to the same memory and both calling delete[] in their destructors.
When you bind &t the address of the object (pointer) gets copied. There are no two separate objects, just one object and a pointer. Similarly the utilities std::ref and std::cref are reference wrappers, that is objects that wrap a different object and provide reference-like semantics. No matter how many times std::ref is copied, all of the copies behave as references to the same object. The object itself is never copied.
What is the reason that you can't move an object to another std::thread? There are situations where it could be useful. For example:
You create a loop that accepts incoming socket connections. It would be nice to move incoming connections to another thread that will handle the connections. You don't need the connection anymore in the accept loop. So why should you create a pointer?
A small test case:
#include <iostream>
#include <thread>
using namespace std;
class Pointertest
{
public:
Pointertest() {cout << "Constructor";}
Pointertest(Pointertest &pointertest) {cout << "Copy";}
Pointertest(Pointertest &&pointertest) {cout << "Move";}
~Pointertest() {cout << "Destruct";}
};
void foo(Pointertest &&pointertest)
{
}
int main()
{
Pointertest pointertest;
foo(std::move(pointertest)); //Works
thread test(foo,std::move(pointertest)); //**cannot convert parameter 1 from 'Pointertest' to 'Pointertest &&'**
}
The std::thread constructor has to treat the arguments you give it somewhat differently from most forwarding functions.
The reason for this is due to questions of when the thread actually gets started. If the part of the function invocation that actually created the function argument gets run long after the thread object is created (which is entirely legal behavior), then the object that needs to be moved from may have long since been destroyed.
Just consider an altered version of your code:
std::thread some_func()
{
Pointertest pointertest;
thread test(foo,std::move(pointertest));
return test;
}
This is perfectly valid (the thread will be moved out of the function). However, there's a big problem. foo may not have been called yet. And since foo takes its parameter by reference, it now has a reference to a stack variable that has been destroyed.
That's bad. But even if foo took its parameter by value, it would change nothing. Because the actual movement into that parameter doesn't happen until some indeterminate time after the thread has been started. The attempt to move into the parameter will still use an rvalue reference to a stack variable that has been destroyed. Which again is bad.
Therefore, std::thread constructor does something different. It copy/moves the arguments you give it into internal storage (this is done on the current thread). Then it uses those values as arguments for the actual function call (this is done on the new thread).
According to the standard, the thread constructor should treat pass these internal variables to your functions as temporaries. The standard specifically states INVOKE (DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...), where the DECAY_COPY stuff happens on the original thread, while the INVOKE part happens on the new thread.
So it seems like your thread implementation isn't able to forward the non-copyable parameters through correctly. You should be able to pass a non-copyable type; the arguments are only required to be MoveConstructible.
So this would appear to be a bug in your implementation.
It is possible. Fixing the signature of your copy constructor makes it work for me:
class Pointertest
{
public:
Pointertest() {cout << "Constructor";}
Pointertest(Pointertest const& pointertest) {cout << "Copy";}
// ^^^^^^
Pointertest(Pointertest &&pointertest) {cout << "Move";}
~Pointertest() {cout << "Destruct";}
};
Also, do not forget to join your thread (or detach from it) before your thread object goes out of scope:
int main()
{
Pointertest pointertest;
thread test(foo, std::move(pointertest));
test.join();
// ^^^^^^^^^^^^
}
I have class like this
class variable
{
public:
variable(int _type=0) : type(_type), value(NULL), on_pop(NULL)
{
}
virtual ~variable()
{
if (type)
{
std::cout << "Variable Deleted" <<std::endl;
on_pop(*this);
value=NULL;
}
}
int type;
void* value;
typedef void(*func1)(variable&);
func1 on_pop;
}
And then I push instances into a std::vector like this:
stack.push_back(variable(0));
I expect that the destructor of variable will be called but the if won't enter until a value is assigned to type because I expect the constructor I provide will be called when the instance is copied into the vector. But for some reason it is not.
After calling stack.push_back the destructor (of the copy?) is ran and type has some random value like if the constructor was never called.
I can't seem to figure what I am doing wrong. Please help! ^_^
EDIT:
Ok here is a self contained example to show what I mean:
#include <iostream>
#include <vector>
class variable
{
public:
variable(int _type=0) : type(_type), value(NULL), on_pop(NULL)
{
}
~variable()
{
if (type)
{
std::cout << "Variable Deleted" <<std::endl;
on_pop(*this);
value=NULL;
}
}
int type;
void* value;
typedef void(*func1)(variable&);
func1 on_pop;
};
static void pop_int(variable& var)
{
delete (int*)var.value;
}
static void push_int(variable& var)
{
var.type = 1;
var.value = new int;
var.on_pop = &pop_int;
}
typedef void(*func1)(variable&);
func1 push = &push_int;
int main()
{
std::vector<variable> stack;
stack.push_back(variable(0));
push(stack[stack.size()-1]);
stack.push_back(variable(0));
push(stack[stack.size()-1]);
stack.push_back(variable(0));
push(stack[stack.size()-1]);
return 0;
}
The program above outputs the following:
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Process returned 0 (0x0) execution time : 0.602 s
Press any key to continue.
Welcome to RVO and NRVO. This basically means that the compiler can skip creating an object if it's redundant- even if it's constructor and destructor have side effects. You cannot depend on an object which is immediately copied or moved to actually exist.
Edit: The actual value in the vector cannot be ellided at all. Only the intermediate variable variable(0) can be ellided. The object in the vector must still be constructed and destructed as usual. These rules only apply to temporaries.
Edit: Why are you writing your own resource management class? You could simply use unique_ptr with a custom deleter. And your own RTTI?
Every object that was destructed must have been constructed. There is no rule in the Standard that violates this. RVO and NRVO only become problematic when you start, e.g., modifying globals in your constructors/destructors. Else, they have no impact on the correctness of the program. That's why they're Standard. You must be doing something else wrong.
Ultimately, I'm just not sure exactly WTF is happening to you and why it's not working or what "working" should be. Post an SSCCE.
Edit: In light of your SSCCE, then absolutely nothing is going wrong whatsoever. This is entirely expected behaviour. You have not respected the Rule of Three- that is, you destroy the resource in your destructor but make no efforts to ensure that you actually own the resource in question. Your compiler-generated copy constructor is blowing up your logic. You must read about the Rule of Three, copy and swap and similar idioms for resource handling in C++, and preferably, use a smart pointer which is already provided as Standard like unique_ptr which does not have these problems.
After all, you create six instances of variable- three temporaries on the stack, and three inside the vector. All of these have their destructors called. The problem is that you never considered the copy operation or what copying would do or what would happen to these temporaries (hint: they get destructed).
Consider the equal example of
int main()
{
variable v(0);
push_int(v);
variable v2 = v;
return 0;
}
Variable v is constructed and allocates a new int and everything is dandy. But wait- then we copy it into v2. The compiler-generated constructor copies all the bits over. Then both v2 and v are destroyed- but they both point to the same resource because they both hold the same pointer. Double delete abounds.
You must define copy (shared ownership - std::shared_ptr) or move (unique ownership - std::unique_ptr) semantics.
Edit: Just a quick note. I observe that you actually don't push into items until after they're already in the vector. However, the same effect is observed when the vector must resize when you add additional elements and the fundamental cause is the same.
The destructor is called 6 times. A constructor is called six times. Just not the one you intended.
Ok. I've been reading some more about the intrinsics of different containers and, apparently, the one that does the job I'm trying to accomplish here is std::deque.