How can I access my class instance from a boost thread? - c++

I have the following code (this is some semi-sudo code, which may not compile):
class FooBar {
public:
void a();
void b();
boost::shared_ptr<boost::thread> m_thread;
std::string m_test;
};
void FooBar::a() {
m_test = "Foo bar"
m_thread = shared_ptr<thread>(new thread(bind(&FooBar::b, this)));
}
void FooBar::b() {
cout << m_test;
}
The code cout << test does not yield any output, because m_test is "" instead of "Foo bar". Why is this? I thought that passing this as the 2nd argument to bind would allow me to access the same instance from b() - am I incorrect?

Yes, that works. Here's the "real" version, which does in fact print "Foo bar":
#include <boost/make_shared.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
using namespace boost;
struct FooBar {
void a();
void b();
shared_ptr<thread> m_thread;
std::string m_test;
};
void FooBar::a() {
m_test = "Foo bar";
m_thread = make_shared<thread>(bind(&FooBar::b, this));
}
void FooBar::b() {
std::cout << m_test;
}
int main() {
FooBar fb;
fb.a();
fb.m_thread->join();
return 0;
}
The code cout << test does not yield any output, because m_test is ""
I suspect this is because the object was being destroyed before the thread got around to evaluating the member variable. Note the join(), it's very important.

Related

Thread inside a class with member function from another class

Can someone tell me how can I run a new thread with member function from a object of diffrent class as a member function of this class ? What ever im trying to do Im still getting errors.
no match for call to '(std::thread) (void (Boo::*)(), Boo&)'|
no match for call to '(std::thread) (void (Foo::*)(), Foo*)'|
#include <iostream>
#include <thread>
using namespace std;
class Boo
{
public:
void run()
{
while(1){}
}
};
class Foo
{
public:
void run()
{
t1(&Boo::run,boo);
t2(&Foo::user,this);
}
void user();
~Foo(){
t1.join();
t2.join();
}
private:
std::thread t1;
std::thread t2;
Boo boo;
};
int main()
{
Foo foo;
foo.run();
}
You need to use operator= to assign the threads after construction
Working example below (see it in action):
#include <thread>
#include <iostream>
class Boo
{
public:
void run()
{
int i = 10;
while(i--)
{
std::cout << "boo\n";;
}
}
};
class Foo
{
public:
void run()
{
t1 = std::thread(&Boo::run,boo); // threads already default constructed
t2 = std::thread(&Foo::user,this); // so need to *assign* them
}
void user()
{
int i = 10;
while(i--)
{
std::cout << "foo\n";;
}
}
~Foo()
{
t1.join();
t2.join();
}
private:
std::thread t1;
std::thread t2;
Boo boo;
};
int main()
{
Foo foo;
foo.run();
}

Does std::future support polymorphism?

Does std::future in c++ support polymorphism?
So, if to store child_class in future<parent_class>, can I after get it after by dynamic_cast<child_class>?
Providing you use a reference or a pointer (probably obvious since it'll fail to compile otherwise)... Yes.
#include <iostream>
#include <future>
using namespace std;
struct Parent {
virtual void a() { cout << "I am parent"; }
};
struct Child : Parent {
virtual void a() { cout << "I am child"; }
};
Child g_c; //just some global for the purposes of the example
int main() {
std::future<Parent&> p = async(launch::async, []() -> Parent& { return g_c; });
auto c = dynamic_cast<Child&>(p.get());
c.a();
return 0;
}
code result here: http://ideone.com/4Qmjvc

Accessing counter from two threads

I have a counter that is being incremented from one thread. In the main thread, I basically print it out by calling data member of a class. In the below code, nothing is being printed out.
#include <iostream>
#include <thread>
#include <windows.h>
#include <mutex>
std::mutex mut;
class Foo
{
public:
Foo(const int& m) : m_delay(m), m_count(0)
{}
void update()
{
std::cout << "count: " << this->m_count << std::endl;
}
void operator()()
{
while (true){
mut.lock();
m_count++;
mut.unlock();
Sleep(m_delay);
}
}
private:
int m_delay;
int m_count;
};
Foo *obj = new Foo(200);
int main()
{
std::thread *t = new std::thread(*obj);
t->join();
while(true)
{
obj->update();
Sleep(10);
}
return 0;
}
The problem with the original code is that this copies the Foo object:
std::thread *t = new std::thread(*obj);
That means that the increments happen to the copy, and so the value in the original Foo never changes, and so when main prints it out (if you move the misplaced join()) the value is always the same.
A solution is to use a reference not a copy:
std::thread *t = new std::thread(std::ref(*obj));
You also need to protect the read of the variable by the mutex (or use std::atomic<int> for the counter) to avoid undefined behaviour caused by concurrently reading and writing a non-atomic variable.
You should also stop using mut.lock() and mut.unlock() directly, use a scoped lock instead.
There's also no need to create things on the heap unnecessarily, overusing new is a bad habit of people who learnt Java and C# first.
You can also make the code portable by replacing the Windows-specific Sleep call with standard C++.
A correct version would be:
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
std::mutex mut;
class Foo
{
public:
Foo(std::chrono::milliseconds m) : m_delay(m), m_count(0)
{}
void update()
{
int count = 0;
{
std::lock_guard<std::mutex> lock(mut);
count = m_count;
}
std::cout << "count: " << count << std::endl;
}
void operator()()
{
while (true)
{
{
std::lock_guard<std::mutex> lock(mut);
m_count++;
}
std::this_thread::sleep_for(m_delay);
}
}
private:
std::chrono::milliseconds m_delay;
int m_count;
};
Foo obj(std::chrono::milliseconds(200));
int main()
{
std::thread t(std::ref(obj));
while(true)
{
obj.update();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
t.join();
return 0;
}
Alternatively, use an atomic variable so you don't need the mutex:
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
class Foo
{
public:
Foo(std::chrono::milliseconds m) : m_delay(m), m_count(0)
{}
void update()
{
std::cout << "count: " << m_count << std::endl;
}
void operator()()
{
while (true)
{
m_count++;
std::this_thread::sleep_for(m_delay);
}
}
private:
std::chrono::milliseconds m_delay;
std::atomic<int> m_count;
};
Foo obj(std::chrono::milliseconds(200));
int main()
{
std::thread t(std::ref(obj));
while(true)
{
obj.update();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
t.join();
return 0;
}

bind shared_from_this the memory will not be released

#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/enable_shared_from_this.hpp>
class A: public boost::enable_shared_from_this<A>
{
typedef boost::function<int()> GET;
public:
A()
{
std::cout << "A::A() " << this << std::endl;
}
~A()
{
std::cout << "A::~A()" << this <<std::endl;
}
void set()
{
myget=boost::bind(&A::get, shared_from_this());
}
Here is the problem: it will not be released when I bind it with with shared_from_this(). But if I bind it with this (boost::bind(&A::get, this)), the instance will be released.
int getI()
{
myget();
}
inline int get()
{
return 1;
}
private:
GET myget;
};
void test()
{
boost::shared_ptr<A> a(new A);
a->set();
a->getI();
}
int main()
{
test();
return 0;
}
My question is: why the instance of A is never released even if the program have been shut down?
The problem is that the myget variable prevents the destructor from ever running.
So you can't even do
~A() {
std::cout << "A::~A()" << this << std::endl;
myget = {};
}
This is what weak-pointers have been invented for. In this particular case though, you could simply use this as there is no way that myget can be accessed after the lifetime of A

Noob boost::bind member function callback question

#include <boost/bind.hpp>
#include <iostream>
using namespace std;
using boost::bind;
class A {
public:
void print(string &s) {
cout << s.c_str() << endl;
}
};
typedef void (*callback)();
class B {
public:
void set_callback(callback cb) {
m_cb = cb;
}
void do_callback() {
m_cb();
}
private:
callback m_cb;
};
void main() {
A a;
B b;
string s("message");
b.set_callback(bind(A::print, &a, s));
b.do_callback();
}
So what I'm trying to do is to have the print method of A stream "message" to cout when b's callback is activated. I'm getting an unexpected number of arguments error from msvc10. I'm sure this is super noob basic and I'm sorry in advance.
replace typedef void (*callback)(); with typedef boost::function<void()> callback;
A bound function doesn't produce an ordinary function, so you cannot just store it in a regular function pointer. However, boost::function is able to handle anything as long as it is callable with the correct signature, so that's what you want. It will work with a function pointer, or a functor created with bind.
After a few corrections to your code, I came up with this:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
// i prefer explicit namespaces, but that's a matter of preference
class A {
public:
// prefer const refs to regular refs unless you need to modify the argument!
void print(const std::string &s) {
// no need for .c_str() here, cout knows how to output a std::string just fine :-)
std::cout << s << std::endl;
}
};
// holds any arity 0 callable "thing" which returns void
typedef boost::function<void()> callback;
class B {
public:
void set_callback(callback cb) {
m_cb = cb;
}
void do_callback() {
m_cb();
}
private:
callback m_cb;
};
void regular_function() {
std::cout << "regular!" << std::endl;
}
// the return type for main is int, never anything else
// however, in c++, you may omit the "return 0;" from main (and only main)
// which will have the same effect as if you had a "return 0;" as the last line
// of main
int main() {
A a;
B b;
std::string s("message");
// you forget the "&" here before A::print!
b.set_callback(boost::bind(&A::print, &a, s));
b.do_callback();
// this will work for regular function pointers too, yay!
b.set_callback(regular_function);
b.do_callback();
}