Pass a point into a thread and have it modified - c++

I need to keep reference of an object passed into a thread. The way the environment is setup I must keep application specific drawing in the same thread it was initiated. So I tuck away app init code in a thread and then get a reference to a custom component I'm interested in.
This isn't working. The app loads and shows up fine but the pointer to the app in the main thread is always null. Even if I use std::shared_ptr or std::ref. Doesn't seem to matter what I do, the pointer is always null.
#include <thread>
#include <iostream>
class SomeClass {
public:
int value;
SomeClass() { value = 0; }
};
void ExecuteThread(SomeClass* c) {
c = new SomeClass();
c->value = 555;
}
int main(int argc, char** argv) {
SomeClass* c = nullptr;
// std::ref(c) doesn't work
// Have also tried passing std::shared_ptr<SomeClass>
std::thread t1 = std::thread(&ExecuteThread, c);
t1.join();
std::cout << "c: " << c << "\n";
std::cout << "c->value: " << c->value << "\n";
return 0;
}

Just so that people do not get confused by incorrect self-answer, I am providing my own, correct answer.
The prime issue with OPs code is the fact that passing pointer by value copies the pointer, and any modification to it will not affect the original. Threads do not change this fact, and do add nothing to it. In particular, the code can be illustrated as
void change(int* k) {
k = nullptr;
}
int i;
k = &i;
change(k);
// k here is still the same as before calling `change`
If one wants to change passed pointer, it should be passed as a reference: void change(int*& k).
Having threads here changes things slightly. Since there is no way to pass something to a std::thread constructor by reference, std::ref needs to be used. The function signature should still accept pointer by reference, and std::ref should be used where thread is created:
auto t = std::thread(change, std::ref(k))

std::thread secretly makes copies of everything you pass as an argument including pointer data. This is incredibly misleading. The only way around that is to pass an address to a pointer and have the thread copy that. Then in your thread's task, deference to a pointer.
#include <thread>
#include <iostream>
class SomeClass {
public:
int value;
SomeClass() { value = 0; }
};
void ExecuteThread(SomeClass** c) {
*c = new SomeClass();
*c->value = 555;
}
int main(int argc, char** argv) {
SomeClass* c = nullptr;
std::thread t1 = std::thread(&ExecuteThread, &c);
t1.join();
std::cout << "c: " << c << "\n";
std::cout << "c->value: " << c->value << "\n";
return 0;
}

Related

Shared_ptr of casted object becomes empty after casting

I'm learning to use std::any and std::any_cast, it's not working as I expected: after casting, the internal shared_ptr of casted object becomes empty.
Here is the simplified code to show the issue, it's hard for me to reason about why after inserting the pointer into the map, the pointed object has changed: shared_ptr no longer points to the original value and becomes empty. I'd love to learn why this behavior happens!
Note I am casting to pointer AA* and store the pointer in an unsorted map, since in real world case I cannot copy AA object, it's a workaround.
Thanks a lot!
struct AA {
std::shared_ptr<int> m_ptr = std::make_shared<int>(22);
int get() {
return *m_ptr;
}
};
struct Cache {
std::unordered_map<std::string, std::any> map;
void insert(std::string str) {
auto a_ptr = std::make_unique<AA>();
map[str] = std::make_any<AA*>(a_ptr.get());
// this casting works as expected, output is 22
auto casted = std::any_cast<AA*>(map[str]);
std::cout <<"inside insert: " << casted->get() << std::endl;
}
};
int main(int argc, char** argv) {
Cache cache;
cache.insert("aa");
auto data = std::any_cast<AA*>(cache.map["aa"]);
// this won't work, output is 0, why?
std::cout << "in main: " << data->get() << std::endl;
}
godbolt demo

How to start a variable number of threads in C++?

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.

How to safely use callbacks when the bound function could be deleted

In the following code, we are creating an object, bind one function and call it before then after deleting the object.
This obviously leads to a segmentation fault as the underlying object was used after deletion.
In the context of a library providing callbacks for asynchronous data, how are we supposed to prevent callback functions to point to a nullptr?
You can test at cpp.sh/5ubbg
#include <memory>
#include <functional>
#include <iostream>
class CallbackContainer {
public:
std::string data_;
CallbackContainer(std::string data): data_(data) {}
~CallbackContainer() {}
void rawTest(const std::string& some_data);
};
void CallbackContainer::rawTest(const std::string& some_data) {
std::cout << data_ << " " << some_data << std::endl;
}
int main(int /* argc */, char const** /* argv */) {
std::unique_ptr<CallbackContainer> container;
container.reset(new CallbackContainer("Internal data"));
auto callback = std::bind(&CallbackContainer::rawTest, container.get(), std::placeholders::_1);
callback("Before");
std::cout << &callback << std::endl;
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}
Returns:
> Internal data Before
> 0x7178a3bf6570
> 0x7178a3bf6570
> Error launching program (Segmentation fault)
If you can share ownership, do this:
int main(int /* argc */, char const** /* argv */) {
std::shared_ptr<CallbackContainer> container; // shared pointer
container.reset(new CallbackContainer("Internal data"));
// shared with functor
auto callback = std::bind(&CallbackContainer::rawTest, container, std::placeholders::_1);
callback("Before");
std::cout << &callback << std::endl;
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}
If not, you should somehow pass invalidity to function object explicitly.
This assumes that you know when container is deleted, and manually invalidate explicitly before that:
int main(int /* argc */, char const** /* argv */) {
std::unique_ptr<CallbackContainer> container;
container.reset(new CallbackContainer("Internal data"));
std::atomic<CallbackContainer*> container_raw(container.get());
auto callback = [&container_raw] (std::string data)
{
if (auto c = container_raw.load())
c->rawTest(data);
};
callback("Before");
std::cout << &callback << std::endl;
container_raw.store(nullptr);
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}
For asio cases, usually shared_from_this() is used, like std::bind(&MyClass::MyMemFunc, shared_from_this(), ptr);
The way I prefer while working with boost asio:
I faced the same issue while working with boost asio. We need to register callbacks to io_service and it was difficult to implement some sort of Manager class which manages lifetime of the objects we may create.
So, I implement something that was suggested by Michael Caisse in cppcon2016. I started passing the shared_ptr to the object to the std::bind.
I used to extend the lifetime of the object and in the callback, you can decide to either extend the lifetime of the object again (by registering the callback again) or let it die automatically.
std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();
auto func = std::bind(&MyClass::MyMemFunc, this, ptr);
ptr.reset();
In the context of a library providing callbacks for asynchronous data, how are we supposed to prevent callback functions to point to a nullptr?
I wouldn't say that's the best solution but using by my above approach, you can detect if you need to proceed further in your callback or not.
It might not be the efficient way but it won't cause any undefined behavior.
void CallbackContainer::rawTest(const std::string& some_data, std::shared<CallbackContainer> ptr)
{
if (ptr.use_count() == 1) {
// We are the only owner of the object.
return; // and the object dies after this
}
std::cout << data_ << " " << some_data << std::endl;
}
EDIT:
An example code that shows how to do it using std::enable_shared_from_this:
#include <iostream>
#include <memory>
#include <functional>
class ABCD: public std::enable_shared_from_this<ABCD> {
public:
void call_me_anytime()
{
std::cout << "Thanks for Calling Me" << std::endl;
}
public:
ABCD(void)
{
std::cout << "CONSTRUCTOR" << std::endl;
}
~ABCD(void)
{
std::cout << "DESTRUCTOR" << std::endl;
}
};
int main(void)
{
auto ptr = std::make_shared<ABCD>();
auto cb = std::bind(&ABCD::call_me_anytime, ptr->shared_from_this());
ptr.reset();
std::cout << "RESETING SHARED_PTR" << std::endl;
std::cout << "CALLING CALLBACK" << std::endl;
cb();
std::cout << "RETURNING" << std::endl;
return 0;
}
Output:
CONSTRUCTOR
RESETING SHARED_PTR
CALLING CALLBACK
Thanks for Calling Me
RETURNING
DESTRUCTOR
As a followup, we decided to use roscpp method which is similar to Alex Guteniev's proposition.
Instead of doing std::bind explicitly, we use it internally and keep the parent as std::weak_ptr<const void> pointer to the std::shared_ptr<P> (as it would conflict with unique_ptr).
The API looks like:
std::shared_ptr<Container> container;
queue.subscribe(&Container::callback_method, container);
The subscription function is as following with T the explicit type of the data (Class-wise) but P the implicit class of the Parent class (Container in this case).
template <class P>
std::shared_ptr<ThreadedQueue<T>> subscribe(void (P::*function_pointer)(std::shared_ptr<const T>), std::shared_ptr<P> parent, size_t queue_size = -1) {
callback_ = std::bind(function_pointer, parent.get(), std::placeholders::_1);
parent_ = std::weak_ptr<const void>(parent);
}
When calling the callback, we do the following check:
if(auto lock = parent_.lock()) {
callback_(data);
}

std::cout changing the variable value

I was coding my function is properly returning a pointer to a reference.
I found that although the function was returning what it was suppose to do, however, std::cout was modifying the results.
Am I doing anything wrong here?
How to rectify this behaviour?
Please refer the following code snippet,
#include "stdafx.h"
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass(int x_):m_Index(x_){}
int m_Index;
};
void myfunction(int *&currentIndex, MyClass obj)
{
currentIndex = &obj.m_Index;
}
int _tmain(int argc, _TCHAR* argv[])
{
MyClass obj(5);
int *Index = NULL;
myfunction(Index, obj);
int curr_Index = *Index;
cout << "Index = " << curr_Index << std::endl; // This works fine.
cout << "Index = " << *Index << std::endl; // This modifies *Index
return 0;
}
void myfunction(int *&currentIndex, MyClass obj)
{
currentIndex = &obj.m_Index;
}
Invokes undefined behavior because obj is only valid for the life of the function call. You keep a pointer to it (or one of it's members) which you use AFTER it has gone out of scope.
You can solve either by pointing to something that doesn't go out of scope (see #songyuanyao's answer). In this case it isn't clear why you need pointers. myfunction could just return the index.
The obj parameter is passed by value, so a copy is made that will be destroyed when the function exits. currentIndex is being set to point to an invalid address, and dereferencing it is undefined behavior. It might work well, or it might not work, anything is possible.
One solution is to make obj be passed by reference instead of by value:
void myfunction(int *&currentIndex, MyClass& obj)
{
currentIndex = &obj.m_Index;
}

How to call method of wrapped object by unique_ptr?

I'm able to compile the following code where I pass a "callback" to an object (Table). What I'm trying to do now is inside Table, call the handle method defined in EventListener
#include <iostream>
#include <vector>
#include <memory>
class Table {
public:
struct Listener{
virtual void handle(int i) = 0;
};
std::vector<std::unique_ptr<Listener>> listeners_;
void add_listener(std::unique_ptr<Listener> l){
listeners_.push_back(std::move(l));
}
};
struct EventListener: public Table::Listener {
void handle(int e){
std::cout << "Something happened! " << e << " \n";
}
};
int main(int argc, char** argv)
{
Table table;
std::unique_ptr<EventListener> el;
table.add_listener(std::move(el));
return 0;
}
EDIT ****
This is what Im trying inside Table. It results in a segmentation fault:
for (auto t =0; t < (int)listeners_.size(); ++t) {
listeners_[t]->handle(event);
}
It doesn't work because you never created an object for it to be called on, just a pointer. The pointer inside the vector will be nullptr and therefore calling the function on it will crash. unique_ptr has absolutely nothing to do with this problem.
Half the problem is that Table cannot handle nullptr but doesn't check for it, and the other half the problem is that Table cannot handle nullptr but main passes one in anyway.
The iteration code is not the problem at all.
As mentioned in the answer by Puppy the line
std::unique_ptr<EventListener> el;
creates an empty std::unique_ptr. This causes the code for nivoking the
listeners to later dereference a nullptr.
A simple fix for your example is to create a listener and use that
when creating the unique_ptr:
struct EventListener: public Table::Listener {
void handle(int e){
std::cout << "Something happened! " << e << " \n";
}
};
// in main()
std::unique_ptr<NoOpListener> el{ new NoOpListener };
table.add_listener(std::move(el));
As mentioned in the comments your code should ensure that nullptr
isn't allowed. One way of doing this would be to add a check for
nullptr in add_listener and throw an exception or silently ignore
them. The first option is the better solution of the two as it
signals the caller that something is wrong.
But I don't see why you would store listeners in std::unique_ptrs.
The use for std::unique_ptr is for ownership. I do not see why the
observed instance should own the listeners. There is another alternative
that I think is better; use std::function<>() and pass it by value.
This disallows the use of nullptr and has the added bonus of accepting
not only function objects, but also normal functions and lambdas as shown
in the following code:
#include <iostream>
#include <vector>
#include <memory>
#include <functional>
class Table {
public:
std::vector<std::function<void(int)>> listeners_;
void add_listener(std::function<void(int)> l) {
listeners_.push_back(l);
}
void invoke_listeners(int event)
{
for(auto l : listeners_) {
l(event);
}
}
};
struct NoOpListener {
void operator() (int i) {
std::cout << "NoOpListener::operator()(" << i << ")" << std::endl;
}
};
void cb(int i) {
std::cout << "cb(" << i << ")" << std::endl;
}
int main(int argc, char** argv)
{
Table table;
table.add_listener(NoOpListener{});
table.add_listener(cb);
table.add_listener([](int i) { std::cout << "[lambda](" << i << ")" << std::endl; });
table.invoke_listeners(10);
return 0;
}
NOTE: As you can see I also used the C++11 ranged-for construct for iterating
over the listeners.