How do I create a std::vector of objects, and each object has a boost::thread encapsulated inside.
class INSTRUMENT {
public:
INSTRUMENT() : m_thread(new boost::thread(&INSTRUMENT::Start, this)) {
x = "abc";
}
~INSTRUMENT() {}
void Start();
public:
std::string x;
boost::shared_ptr<boost::thread> m_thread;
};
void INSTRUMENT::Start() {
try {
while (1) {
boost::this_thread::interruption_point();
std::cout << "here " << x << std::endl;
}
} catch (boost::thread_interrupted &thread_e) {
std::cout << "exit " << x << std::endl;
} catch (std::exception &e) {
}
}
std::vector<INSTRUMENT> m_inst_vector;
for (int i = 0; i < 5; i++) {
m_inst_vector.push_back(INSTRUMENT());
}
The code compiles fine, but the output is just some garbage, not "abc" as expected. In debug, I notice that ~INSTRUMENT() is called every time when .push_back() is called.
I tried not to use boost::group_thread, because of the limitation on the current design. Just wondering whether it is possible to have a std::vector of objects with a thread inside, or any suggestion to a similar design would be very helpful.
I find a similar thread on SO. It mentioned about move-semantics supported in compiler, but didn't explain what it is.
How can I add boost threads to a vector
Thanks.
There are two problems with this code.
Firstly, the thread starts running immediately the boost::thread object is constructed, so you need to ensure that any data it accesses is initialized beforehand --- i.e. initialize x in the member initialization list prior to constructing the thread.
Secondly, the thread uses the this pointer of the INSTRUMENT object, so your object is tied to a specific address. std::vector copies values around: when you call push_back then it copies the object into the vector, and adding additional elements may copy the others around if a new memory block has to be allocated to make room. This is the cause of the destructor calls you see: the temporary is constructed, push_back copies it to the vector, and then the temporary is destructed.
To fix this, you need to ensure that once constructed your INSTRUMENT objects cannot be moved or copied, as copies have the wrong semantics. Do this by making your copy constructor and assignment operator private and unimplemented (or marking them deleted if you have a recent compiler that supports this new C++11 construct), or deriving from boost::noncopyable. Having done this then you no longer need a shared_ptr for the thread, as it cannot be shared, so you can just construct it directly.
If INSTRUMENT is not copyable, you can't store it directly in a vector, so use something like boost::shared_ptr<INSTRUMENT> in the vector. This will allow the vector to freely copy and reshuffle its elements, without affecting the address of the INSTRUMENT object, and ensuring that it is correctly destroyed at the end.
class INSTRUMENT: boost::noncopyable {
public:
INSTRUMENT() : x("abc"),m_thread(&INSTRUMENT::Start, this) {
}
~INSTRUMENT() {}
void Start();
public:
std::string x;
boost::thread m_thread;
};
void INSTRUMENT::Start() {
try {
while (1) {
boost::this_thread::interruption_point();
std::cout << "here " << x << std::endl;
}
} catch (boost::thread_interrupted &thread_e) {
std::cout << "exit " << x << std::endl;
} catch (std::exception &e) {
}
}
std::vector<boost::shared_ptr<INSTRUMENT> > m_inst_vector;
for (int i = 0; i < 5; i++) {
m_inst_vector.push_back(boost::shared_ptr<INSTRUMENT>(new INSTRUMENT));
}
EDIT: You have a race condition in your code. The thread starts before x gets initialized.
You should change the vector to vector<boost::shared_ptr<INSTRUMENT> >, and remove the boost::shared_ptr from inside INSTRUMENT.
class INSTRUMENT {
public:
INSTRUMENT() {
x = "abc";
m_thread = boost::thread(&INSTRUMENT::Start, this)
}
~INSTRUMENT() {}
void Start();
public:
std::string x;
boost::thread m_thread;
};
for (int i = 0; i < 5; i++) {
m_inst_vector.push_back(boost::shared_ptr<INSTRUMENT>(new INSTRUMENT()));
}
Related
I have an Object with multiple shared_ptrs pointing to it, and its reference count use_count in the associating control block is bigger than 1.
Now, I want to deconstruct the Object, but I do not know where are all those shared_ptrs, so I cannot find and deconstruct them before I deconstruct the Object.
If I just deconstruct the Object, it will make those shared_ptrs become dangling. Therefore, under this situation, how to delete the Object with use_count bigger than 1 but have no idea about all its shared_ptrs?
Thanks for any suggestions!
If you have access to code of Object class and can modify it then you can do following steps (you may jump straight away to final code afterwards):
Create special structure Fields that contains all fields of original Object.
Store Fields as heap-allocated pointer field p_.
In original Object class make all original fields as references pointing to fields of Fields heap allocated object.
Add destroyed_ bool flag that marks that Object was already destroyed. This flag becomes true after first call of destructor.
In every method check that destroyed_ is not true, otherwise throw an exception. Because NONE of methods can be used when object is already destroyed. You may also just show a message with some error instead of throwing exception and return from method without doing anything. Up to you how to handle this error.
Inside destructor on first call make all cleanup as usual. And mark destroyed_ as true. Second call to destructor should just silently exit due to destroyed_ being already true.
All copy constructors and assignment operators should be implemented as usual. Example in code below.
To delete object before all shared pointers are freed just call ptr->~Object(); destructor, here ptr is any shared pointer, or use a convenience function std::destroy_at, like this std::destroy_at(ptr.get());.
In code below if last DoSomething() is not called (try to comment it out) then program finishes without exception, although warning is shown about calling destructor second time.
Try it online!
#include <iostream>
#include <memory>
class Object {
public:
Object()
: p_(new Fields{}), f0_(p_->f0_), f1_(p_->f1_) {}
Object(Object const & o)
: p_(new Fields{}), f0_(o.f0_), f1_(o.f1_) {}
Object & operator = (Object const & o) {
f0_ = o.f0_;
f1_ = o.f1_;
return *this;
}
void DoSomething() {
if (destroyed_)
throw std::runtime_error("Object already destroyed!");
f0_ += 1;
f1_ += std::to_string(f0_) + " ";
std::cout << "DoSomething: '" << f1_ << "'" << std::endl;
}
~Object() {
if (destroyed_) {
std::cout << "Called destructor of destroyed object..."
<< std::endl;
return;
}
// Process fields cleanup here...
delete p_;
p_ = nullptr;
destroyed_ = true;
}
private:
struct Fields {
int f0_ = 0;
std::string f1_;
};
Fields * p_ = nullptr;
bool destroyed_ = false;
int & f0_;
std::string & f1_;
};
int main() {
try {
std::shared_ptr<Object> o0 = std::make_shared<Object>();
{
std::shared_ptr<Object> o1 = o0;
o1->DoSomething();
o1->DoSomething();
// Call destructor when you don't need object.
// Even if some shared_ptrs still use it.
o1->~Object();
}
o0->DoSomething();
return 0;
} catch (std::exception const & ex) {
std::cout << "Exception: " << ex.what() << std::endl;
return -1;
}
}
Output:
DoSomething: '1 '
DoSomething: '1 2 '
Called destructor of destroyed object...
Exception: Object already destroyed!
Similar code to above can be also implemented using C++17 std::optional instead of heap pointer, this solution is even better because it doesn't use any heap allocation, all fields are located inside object's body (i.e. stack allocation).
Try it online!
#include <iostream>
#include <memory>
#include <optional>
class Object {
public:
Object()
: p_(Fields{}), f0_(p_->f0_), f1_(p_->f1_) {}
Object(Object const & o)
: p_(Fields{}), f0_(o.f0_), f1_(o.f1_) {}
Object & operator = (Object const & o) {
f0_ = o.f0_;
f1_ = o.f1_;
return *this;
}
void DoSomething() {
if (destroyed_)
throw std::runtime_error("Object already destroyed!");
f0_ += 1;
f1_ += std::to_string(f0_) + " ";
std::cout << "DoSomething: '" << f1_ << "'" << std::endl;
}
~Object() {
if (destroyed_) {
std::cout << "Called destructor of destroyed object..."
<< std::endl;
return;
}
// Process fields cleanup here...
p_ = std::nullopt;
destroyed_ = true;
}
private:
struct Fields {
int f0_ = 0;
std::string f1_;
};
std::optional<Fields> p_;
bool destroyed_ = false;
int & f0_;
std::string & f1_;
};
int main() {
try {
std::shared_ptr<Object> o0 = std::make_shared<Object>();
{
std::shared_ptr<Object> o1 = o0;
o1->DoSomething();
o1->DoSomething();
// Call destructor when you don't need object.
// Even if some shared_ptrs still use it.
o1->~Object();
}
o0->DoSomething();
return 0;
} catch (std::exception const & ex) {
std::cout << "Exception: " << ex.what() << std::endl;
return -1;
}
}
Output:
DoSomething: '1 '
DoSomething: '1 2 '
Called destructor of destroyed object...
Exception: Object already destroyed!
How to delete an Object whose associating use_count is bigger than 1?
By reducing the use count to 0. This can be achieved by destroying or reassigning the shared pointers that currently point to the object.
but I do not know where are all those shared_ptrs
Then you must solve the problem that prevents you from knowing all those pointers.
Or, you could consider that perhaps there is a reason why those pointers exist, and that perhaps the object isn't supposed to be deleted yet, since it's apparently being used by some part of the program.
I am searching for a way to start multiple threads whose exact number can only be determined at runtime. The threads are not dependent on each other, so it's a fire-and-forget kind of problem.
The threads do need some context which is stored as internal variables of a class (Foo). Some of these variables are references. The class also holds a method that should be executed as the thread function (bar).
#include <iostream>
#include <string>
#include <vector>
#include <thread>
class Foo
{
public:
Foo(int a){
std::cout << "Created" << std::endl;
m_a = new int(a);
}
~Foo(){
std::cout << "Destroyed" << std::endl;
delete m_a;
}
void bar() {
std::cout << "Internal var: " << *m_a << std::endl;
}
private:
int* m_a;
};
int main() {
for(int i = 0; i < 5; i++) {
std::thread t(&Foo::bar, std::ref(Foo(i)));
// the threads will be joined at a later point, this is for demo purposes
}
return 0;
}
I get a compile error at this point:
error: use of deleted function ‘void std::ref(const _Tp&&) [with _Tp = Foo]’
I get it that this error is caused because of the temporary nature of the object created in the for-loop. But if I remove the std::ref function, I get a segfault: double free or corruption (fasttop)
I am sure that there must be a way of doing this, but I am unaware of that. I would expect some output like (probably in this order, but not guaranteed):
Created
Internal var: 0
Destroyed
Created
Internal var: 1
Destroyed
...
Thanks!
Problem 1: Foo is missing a copy/move constructor. See The rule of three/five/zero.
Add a copy constructor:
Foo(Foo const& that) : m_a(new int(*that.m_a)) {}
And/or a move constructor:
Foo(Foo && that) : m_a(that.m_a) { that.m_a = nullptr; }
Problem 2: Foo(i) is a temporary instance of Foo, it lives until the end of the full-expression (the ;).
std::thread t(&Foo::bar, std::ref(Foo(i)));
// ^
// Foo(i) is dead at this point while the thread is starting!
You want it to live longer than that, in order to be usable inside the thread.
For example, like this (also answers your question about creating threads in a loop):
int main() {
std::vector<Foo> inputs;
std::vector<std::thread> threads;
for(int i = 0; i < 5; i++) {
inputs.emplace_back(i);
threads.emplace_back(&Foo::bar, &inputs.back());
}
for (auto& t : threads) {
t.join();
}
}
Note: std::ref(Foo(i)) doesn't compile because it has protection against returning references to temporaries (precisely to prevent issues like these).
Here is a minimaly fixed version of your code:
it includes the move ctor for Foo class (and explicitely deletes copy ctor)
it moves the threads into a vector
it joins the threads
Code:
#include <string>
#include <vector>
#include <thread>
#include <iostream>
class Foo
{
public:
Foo(int a) {
std::cout << "Created" << std::endl;
m_a = new int(a);
}
~Foo() {
if (m_a != NULL) {
std::cout << "Destroyed" << std::endl;
delete m_a;
}
}
Foo(const Foo& other) = delete; //not used here
Foo(Foo&& other) {
std::cout << "Move ctor" << '\n';
m_a = other.m_a;
other.m_a = nullptr;
}
void bar() {
std::cout << "Internal var: " << *m_a << std::endl;
}
private:
int* m_a;
};
int main() {
std::vector<std::thread> vec;
for (int i = 0; i < 5; i++) {
std::thread t(&Foo::bar, Foo(i));
vec.push_back(std::move(t));
}
for (auto& t : vec) {
t.join();
}
return 0;
}
The chief design failure seems that t is a variable inside the loop. That means it's destroyed at the end of each iteration - you never have 5 std::thread instances at the same time. Also, you fail to call join on those threads.
The std::ref apparently hides this problem and replaces it with another problem, but your original thread creation was correct: std::thread t(&Foo::bar, Foo(i)).
You probably want a std::list<std::thread>, and use std::list::emplace_back to create a variable amount. std::list<std::thread> allows you to remove threads in any order from the list.
I designed an App that holds a stack of layers and an active obj.
When a Layer is attached to the App, the Layer tells App what an active object is. But my design causes a sigtrap when deallocating.
It cause sigtrap because the destruction of shared_ptr<Obj> m_obj in App happens first which reduce the use_count to 1. Then the onDetech function gets call, setting the active shared_ptr<Obj> m_obj to nullptr and reduce use_count to 0! But the layer still holds an shared_ptr<Obj>.
The code below is a minimal example to reproduce. I notice my code has a reference cycle but I have no idea how to fix this except using a raw pointer for obj in the App class.
I used shared_ptr for obj in App because it makes sense to me that App has the shared ownership of obj. Should I not use shared_ptr in this case?
class App;
class Obj {
public:
~Obj() { std::cout << "obj destruct" << std::endl; }
};
class Layer {
public:
Layer() { m_obj = std::make_shared<Obj>(); }
~Layer() { std::cout << m_obj.use_count() << std::endl; }
void onAttach(App *app);
void onDetach();
std::shared_ptr<Obj> m_obj;
private:
App *m_app;
};
class LayerStack {
public:
void pushLayer(App *app, std::shared_ptr<Layer> layer) {
m_layers.push_back(layer);
layer->onAttach(app);
}
~LayerStack() {
for (auto &layer : m_layers) {
layer->onDetach();
}
}
private:
std::vector<std::shared_ptr<Layer>> m_layers;
};
class App {
public:
App() {
m_defaultLayer = std::make_shared<Layer>();
m_stack.pushLayer(this, m_defaultLayer);
}
~App() {}
LayerStack m_stack;
std::shared_ptr<Layer> m_defaultLayer;
std::shared_ptr<Obj> m_activeObj;
};
void Layer::onAttach(App *app) {
m_app = app;
app->m_activeObj = m_obj;
std::cout << m_obj.use_count() << std::endl;
}
void Layer::onDetach() {
m_app->m_activeObj = nullptr;
std::cout << m_obj.use_count() << std::endl;
}
int main() {
A a;
}
output:
2
obj destruct
-923414512
-923414512
You're accessing m_activeObj after its lifetime has ended, and thus the behavior of your program is undefined.
The sequence of events is as follows:
App object goes out of scope
~App runs
m_activeObj is destroyed; after this its lifetime has ended and it can no longer be accessed
m_defaultLayer is destroyed
m_stack is destroyed
m_layers[0].onDetach() is called
onDetach sets m_app->m_activeObj to nullptr, but its lifetime has already ended, so behavior is undefined.
Irrelevant other stuff; you're already screwed.
The solution is to reorder things so that you don't access m_activeObj after its lifetime has ended. Either move m_stack's declaration after m_activeObj so it gets destroyed first or clear it manually in ~App.
I am working on a multithreading program where a "std::deque< MyObject > myBuffer" is used as a FIFO buffer, a producer thread is constantly adding custom objects to the end of a deque using push_back(), and a consumer thread uses a helper function to retrieve the object and handle the synchronization and mutex.
std::deque< MyObject > myBuffer;
std::mutex mtx;
int main() {
std::thread producerThread(producer());
std::thread consumerThread(consumer());
// other code
return 0;
}
The producer function:
void producer() {
while (somecondition) {
// code producing MyObject object
std::lock_guard<std::mutex> lck(mtx);
myBuffer.push_back(object);
}
}
The consumer function:
void consumer() {
while(somecondition) {
MyObject object1, object2;
if (retrieve(object1)) {
// process object1
}
if (retrieve(object2)) {
// process object2
}
}
}
My current helper function looks like this:
bool retrieve(MyObject & object) {
// other code ...
std::lock_guard<std::mutex> lck(mtx);
if (!myBuffer.empty()) {
object = myBuffer.front();
myBuffer.pop_front();
return true;
} else {
return false;
}
}
However, I quickly realized that deque::front() returns the reference of the first element in the container. And "object" is MyObject&, so based on my understanding, only the reference of the first element in the deque is passed to object and as a result when I call the pop_front(), the element referenced should be gone and the object variable is holding an invalid reference. Surprisingly, when I actually ran the code, everything worked as opposed to what I expected. So could anyone help me understand how this "deque::front() returns the reference" works? Thanks.
It works properly and this is expected behavior.
You don't assign the reference - you can't, C++ references are immutable. You actually copy the value. This is how it is supposed to work. Semantic of foo = ... assignment when foo is a reference is roughly:
"copy the right-hand value to the place referenced by foo".
When there is a reference on the right side, the referenced value is copied.
In your case, object = myBuffer.front(); line copies the front value of deque to variable object1 or object2 in consumer(), respectively to the call. Later call to .pop_front() destroys the value in the deque, but doesn't affect the already copied value.
i can't understand you purpose,Maybe you can try deque::at()
pop_front() removes the first element from queue. It does not delete the object. So, referencing the object after pop_front() call should work.
Update -
#include <iostream>
#include <queue>
#include <algorithm>
class newClass {
public:
newClass () {
}
~newClass () {
std::cout << " Destructor is called. " << "\n";
}
newClass(const newClass &obj) {
std::cout << "Copy is called." << "\n";
}
void print(void) {
std::cout << "Hi there !" << "\n";
}
};
void queueWithPointer(void) {
std::deque<newClass *> deque;
deque.push_back(new newClass());
deque.push_front(new newClass());
newClass *b = deque.front();
std::cout << "pop_front starts" << "\n";
deque.pop_front();
std::cout << "pop_front ends" << "\n";
b->print();
}
void queueWithObjects(void) {
std::deque<newClass> deque;
deque.push_back(newClass());
deque.push_front(newClass());
newClass ba = deque.front();
std::cout << "pop_front starts" << "\n";
deque.pop_front();
std::cout << "pop_front ends" << "\n";
ba.print();
}
int main()
{
queueWithPointer();
// queueWithObjects();
return 0;
}
Above program can be used to understand the behaviour. In case of objects, copy constructor is called and a new copy is stored in deque. When pop_front() is called, the copy is deleted. While in case of pointers, address is copied. So, the address is deleted and not the actual object referenced by the address. You will find that destructor is not called in this case.
I have a class. When this class is instantiated, I want the instance added to a list. When the object is deleted, I want it removed from the list.
So I give the object a shared pointer to itself. I then have a list of weak pointers to those shared pointers. When an object is created, it creates a shared pointer to itself, makes a weak pointer to that, and puts the weak pointer in a list.
When the object is destroyed, the shared pointer is as well. Whenever I try to access a member in the list, I ensure that it hasn't expired and that its use count isn't 0. Despite this, I still crash when the list member is destroyed. Why? Can I get around it? Here's my SSCCE:
#include <iostream>
#include <memory>
#include <vector>
class test
{
private:
std::shared_ptr<test> self;
public:
int val;
test(int set);
test(test ©) = delete; // making sure there weren't issues
// with a wrong instance being deleted
};
std::vector<std::weak_ptr<test>> tests;
test::test(int set):
val(set)
{
this->self = std::shared_ptr<test>(this);
tests.push_back(std::weak_ptr<test>(this->self));
}
void printTests()
{
for (auto i = tests.begin(); i != tests.end(); i++)
{
if (i->use_count() == 0 || i->expired())
{
tests.erase(i);
continue;
}
std::cout << i->lock()->val << std::endl;
}
std::cout << std::endl;
}
int main(int argc, char **argv)
{
{
test t(3);
std::cout << "First tests printing: " << std::endl;
printTests();
} // SEGFAULTS HERE
std::cout << "Second tests printing: " << std::endl;
printTests();
return 0;
}
The output of this program is as follows:
First tests printing:
3
Segmentation fault (core dumped)
Your issue is with how you are creating the self pointer:
this->self = std::shared_ptr<test>(this);
When a shared_ptr is created with this constructor, according to the documentation,
When T is not an array type, constructs a shared_ptr that owns the pointer p.
...
p must be a pointer to an object that was allocated via a C++ new expression or be 0
So the issue is that the shared_ptr is taking ownership of your stack object, so when the object gets destructed (and the shared_ptr along with it), shared_ptr is trying to delete your object that is on the stack. This is not valid.
For your use case, if you expect tests to outlive your vector, then you might be able to just store this.
I think the OP is interested in a solution to his original problem even if it uses a different method than the one he attempted. Here is a simple example of how to add an object to a global list when it is constructed, and remove it when it is deleted. One thing to remember: you must call AddList in every constructor you add to your base class. I didn't know whether you want the list to be accessible outside the class or not, so I added getter functions to return non-const iterators to the list.
class MyClass
{
private:
static std::list<MyClass*> mylist;
std::list<MyClass*>::iterator mylink;
// disable copy constructor and assignment operator
MyClass(const MyClass& other);
MyClass& operator = (const MyClass& other);
void AddList()
{
mylink = mylist.insert(mylist.end(), this);
}
void RemoveList()
{
mylist.erase(mylink);
}
public:
MyClass()
{
AddList();
}
virtual ~MyClass()
{
RemoveList();
}
static std::list<MyClass*>::iterator GetAllObjects_Begin()
{
return mylist.begin();
}
static std::list<MyClass*>::iterator GetAllObjects_End()
{
return mylist.end();
}
virtual std::string ToString() const
{
return "MyClass";
}
};
class Derived : public MyClass
{
virtual std::string ToString() const
{
return "Derived";
}
};
std::list<MyClass*> MyClass::mylist;
int main()
{
std::vector<MyClass*> objects;
objects.push_back(new MyClass);
objects.push_back(new MyClass);
objects.push_back(new Derived);
objects.push_back(new MyClass);
for (std::list<MyClass*>::const_iterator it = MyClass::GetAllObjects_Begin(), end_it = MyClass::GetAllObjects_End(); it != end_it; ++it)
{
const MyClass& obj = **it;
std::cout << obj.ToString() << "\n";
}
while (! objects.empty())
{
delete objects.back();
objects.pop_back();
}
}
This line is trouble:
tests.erase(i);
An iterator pointing to the erased element is invalid, and you can't increment it any longer. Luckily, erase returns a new iterator you can use:
auto i = tests.begin();
while (i != tests.end())
{
if (i->use_count() == 0 || i->expired())
{
i = tests.erase(i);
}
else {
std::cout << i->lock()->val << std::endl;
++i;
}
}