I'm using Boost::thread to implement an InterruptibleThread class, while getting segmentation fault during execution. Any idea?
The source and the output are under below.
interruptiblethread.h
#ifndef INTERRUPTIBLETHREAD_H
#define INTERRUPTIBLETHREAD_H
#include <boost/thread.hpp>
#include <boost/thread/future.hpp>
#include <boost/thread/tss.hpp>
class InterruptFlag
{
public:
inline void set()
{
boost::lock_guard<boost::mutex> guard(_mtx);
_set = true;
}
inline bool is_set()
{
std::cout << "is_set()" << std::endl;
boost::lock_guard<boost::mutex> guard(_mtx);
std::cout << "is_set() end" << std::endl;
return _set;
}
private:
boost::mutex _mtx;
bool _set;
};
extern boost::thread_specific_ptr<InterruptFlag> this_thread_interrupt_flag;
class InterruptibleThread
{
public:
template<typename FunctionType>
InterruptibleThread(FunctionType f)
{
boost::promise<InterruptFlag*> p;
_internal_thread = boost::thread([f, &p]()
{
p.set_value(this_thread_interrupt_flag.get());
f();
});
_interrupt_flag = p.get_future().get();
}
inline void interrupt()
{
if (_interrupt_flag != nullptr)
{
_interrupt_flag->set();
}
}
private:
boost::thread _internal_thread;
InterruptFlag* _interrupt_flag;
};
#endif // INTERRUPTIBLETHREAD_H
interruptiblethread.cpp
#include <iostream>
#include <functional>
#include "interruptiblethread.h"
using std::cout; using std::endl;
using std::function;
boost::thread_specific_ptr<InterruptFlag> this_thread_interrupt_flag;
struct thread_interrupted {};
void interruption_point()
{
cout << "interruption_point()" << endl;
if (this_thread_interrupt_flag->is_set())
{
cout << "is_set" << endl;
throw thread_interrupted();
}
}
void foo()
{
while (true)
{
cout << "iterate" << endl;
try
{
interruption_point();
} catch (const thread_interrupted& interrupt)
{
cout << "catch thread_interrupted" << endl;
break;
}
}
}
int main()
{
InterruptibleThread int_thread(foo);
int_thread.interrupt();
while (true) {}
}
Output:
➜ build ./main
iterate
interruption_point()
is_set()
[1] 44435 segmentation fault ./main
this_thread_interrupt_flag is not initialized. Please initialize it correctly as described here
Your call to is_set is UB.
Related
This is my minimal, reproducible example
#include <memory>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
class BaseClass {
public:
void do_func() {
while(true) {
std::cout << "doing stuff" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
};
int main() {
auto obj = std::make_unique<BaseClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "reset called!" << std::endl;
obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
return 0;
}
I was expecting the object to be deleted after reset is called. Even the code cannot exit because the while loop is blocking, which is understandable. I need to delete the object after a particular event, and cannot wait till the unique_ptr goes out of scope. If I change the do_func to
void do_func() {
std::cout << "doing stuff" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(20));
}
then it is the expected behaviour.
Edit:
Based on your comments I have updated my code to
#include <memory>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
class BaseClass {
public:
BaseClass() : x(1) {
dummy = std::make_shared<SomeClass>();
}
void do_func() {
while(true) {
std::cout << "doing stuff " << dummy->do_stuff(x) << std::endl;
x++;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
private:
int x;
class SomeClass {
public:
int do_stuff(int x) {
return x * x;
}
};
std::shared_ptr<SomeClass> dummy;
};
int main() {
auto obj = std::make_unique<BaseClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "reset called!" << std::endl;
obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
return 0;
}
And now the function does print garbage values. Does that mean I need to explicitly delete dummy in the destructor?
The simplest way to synchronize these two threads would be to use std::atomic_bool
#include <atomic>
class BaseClass {
public:
std::atomic_bool shouldContinueWork = true;
void do_func() {
while(shouldContinueWork) {
std::cout << "doing stuff" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
};
int main() {
auto obj = std::make_unique<BaseClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
obj->shouldContinueWork = false; //the thread will not do anything more after this, but the sleep will need to end on it's own
std::cout << "stopping work!" << std::endl;
// do not remove the object before join is called - you don't know if it will be still accessed from the other thread or not
// obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
// here it is safe to remove the `obj`, main thread is surely the only thread that accesses it
// (but it goes out of scope anyway)
return 0;
}
This solution doesn't take into account stopping the work midway (i.e. whole loop iteration must always be performed) and is generally prone to having a few more or less iterations of work - it should be precise enough when you have sleep of 1s, but with smaller sleep it won't guarantee any exact number of iterations, take that into account. std::condition_variable can be used for more precise control of thread synchronization.
Thanks for all your quick responses! Let me know if this is a good solution
#include <memory>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
class BaseClass {
public:
BaseClass() : x(1) {
dummy = std::make_shared<SomeClass>();
}
virtual ~BaseClass() {
dummy.reset();
}
void do_func() {
while(dummy) {
std::cout << "doing stuff " << dummy->do_stuff(x) << std::endl;
x++;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
private:
int x;
class SomeClass {
public:
int do_stuff(int x) {
return x * x;
}
};
std::shared_ptr<SomeClass> dummy;
};
class DerivedClass : public BaseClass {
};
int main() {
auto obj = std::make_unique<DerivedClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "reset called!" << std::endl;
obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
return 0;
}
The behaviour is now as expected.
I can't close my thread. Am I forgetting to do something? The thread seems like it's saving the value I'm using for close, and then never checks if it has changed. Here is some example code that has an identical effect:
#include "stdafx.h"
#include "Windows.h"
#include <iostream>
#include <thread>
class test {
private:
bool user_wants_thread = true;
bool time_to_close = false;
public:
bool set_timetoclose(bool in) {
time_to_close = in;
if (time_to_close == in) {
return true;
}
return false;
}
void function() {
while (user_wants_thread) {
// CODE
std::cout << time_to_close;
Sleep(100);
if (time_to_close) {
goto close;
}
}
close:
Sleep(1);
}
};
int main() {
test t;
std::thread thread_func(&test::function, t);
Sleep(1000);
bool success;
do {
success = t.set_timetoclose(true);
} while (!success);
thread_func.join();
std::cout << "Closed";
std::cin.get();
}
I removed some unused parts and changed the actual condition to be an atomic<bool> and it seems to work as shown on this link:
http://rextester.com/TWHK12491
I'm not claiming this is absolutely correct, however, but it shows how using the atomic causes synchronization across reads/writes to the value which could result in a data race.
#include "Windows.h"
#include <iostream>
#include <thread>
#include <atomic>
class test {
public:
std::atomic<bool> time_to_close = false;
test()=default;
void function() {
while (!time_to_close) {
std::cout << "Running..." << std::endl;
Sleep(100);
}
std::cout << "closing" << std::endl;
}
};
int main() {
test t;
std::thread thread_func([&t](){t.function();});
Sleep(500);
t.time_to_close = true;
std::cout << "Joining on thread" << std::endl;
thread_func.join();
std::cout << "Closed";
return 0;
}
The following program still interleaves the output to std::cout. I tried to add a std::mutex to control access to std::cout via std::lock_guard, but it still interleaves.
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>
std::mutex global_mtx{};
class Timer {
public:
Timer(size_t time, const std::function<void(void)>& f) : time{std::chrono::milliseconds{time}}, f{f} {}
~Timer() { wait_thread.join(); }
private:
void wait_then_call()
{
std::unique_lock<std::mutex> lck{mtx};
for(int i{10}; i > 0; --i) {
{
std::lock_guard<std::mutex>{global_mtx};
std::cout << "Thread " << wait_thread.get_id() << " countdown at: " << '\t' << i << std::endl;
}
cv.wait_for(lck, time / 10);
}
f();
}
std::mutex mtx;
std::condition_variable cv{};
std::chrono::milliseconds time;
std::function <void(void)> f;
std::thread wait_thread{[this]() {wait_then_call(); }};
};
int main()
{
auto f = []() {std::lock_guard<std::mutex>{global_mtx}; std::cout << "---------------- I waited to print! ----------------" << std::endl; };
Timer t1{3'000,f};
Timer t2{6'000,f};
Timer t3{2'000,f};
Timer t4{1'000,f};
}
Do I need to control access through a separate class or dedicated thread?
Your problem is here: std::lock_guard<std::mutex>{global_mtx}; creates a lock guard and immediately releases it. You need to create a variable to hold the lock, like std::lock_guard<std::mutex> lock{global_mtx};.
One way to prevent forgetting to name the lock is to make a lock object that you can use as an io manipulator:
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>
std::mutex global_mtx{};
struct lockio
{
lockio(std::mutex& m) : lock_(m) {}
std::unique_lock<std::mutex> lock_;
};
std::ostream& operator<<(std::ostream& os, const lockio&) {
return os;
}
class Timer {
public:
Timer(size_t time, const std::function<void(void)>& f) : time{std::chrono::milliseconds{time}}, f{f} {}
~Timer() { wait_thread.join(); }
private:
void wait_then_call()
{
std::unique_lock<std::mutex> lck{mtx};
for(int i{10}; i > 0; --i) {
{
std::cout << lockio(global_mtx) << "Thread " << wait_thread.get_id() << " countdown at: " << '\t' << i << std::endl;
}
cv.wait_for(lck, time / 10);
}
f();
}
std::mutex mtx;
std::condition_variable cv{};
std::chrono::milliseconds time;
std::function <void(void)> f;
std::thread wait_thread{[this]() {wait_then_call(); }};
};
int main()
{
auto f = []() { std::cout << lockio(global_mtx) << "---------------- I waited to print! ----------------" << std::endl; };
Timer t1{3'000,f};
Timer t2{6'000,f};
Timer t3{2'000,f};
Timer t4{1'000,f};
}
Another (probably better) way is to create a little helper template function to wrap the protected operations:
#include <iostream>
#include <thread>
#include <condition_variable>
std::mutex global_mtx{};
template<class Mutex, class F>
decltype(auto) with_lock(Mutex &m, F &&f) {
std::lock_guard<Mutex> lock(m);
return f();
};
class Timer {
public:
Timer(size_t time, const std::function<void(void)> &f) : time{std::chrono::milliseconds{time}}, f{f} {}
~Timer() { wait_thread.join(); }
private:
void wait_then_call() {
std::unique_lock<std::mutex> lck{mtx};
for (int i{10}; i > 0; --i) {
with_lock(global_mtx, [&] {
std::cout << "Thread " << wait_thread.get_id() << " countdown at: " << '\t' << i << std::endl;
});
cv.wait_for(lck, time / 10);
}
f();
}
std::mutex mtx;
std::condition_variable cv{};
std::chrono::milliseconds time;
std::function<void(void)> f;
std::thread wait_thread{[this]() { wait_then_call(); }};
};
int main() {
auto f = []() {
with_lock(global_mtx, []
{
std::cout << "---------------- I waited to print! ----------------" << std::endl;
});
};
Timer t1{3'000, f};
Timer t2{6'000, f};
Timer t3{2'000, f};
Timer t4{1'000, f};
}
one more way:
#include <iostream>
#include <thread>
#include <condition_variable>
struct locked {
std::ostream& cout() const { return std::cout; }
std::ostream& cerr() const { return std::cerr; }
private:
static std::mutex& mutex() {
static std::mutex stdio_mutex;
return stdio_mutex;
}
std::unique_lock<std::mutex> lock_{mutex()};
};
class Timer {
public:
Timer(size_t time, const std::function<void(void)> &f) : time{std::chrono::milliseconds{time}}, f{f} {}
~Timer() { wait_thread.join(); }
private:
void wait_then_call() {
std::unique_lock<std::mutex> lck{mtx};
for (int i{10}; i > 0; --i) {
locked().cout() << "Thread " << wait_thread.get_id() << " countdown at: " << '\t' << i << std::endl;
cv.wait_for(lck, time / 10);
}
f();
}
std::mutex mtx;
std::condition_variable cv{};
std::chrono::milliseconds time;
std::function<void(void)> f;
std::thread wait_thread{[this]() { wait_then_call(); }};
};
int main() {
auto f = []() {
locked().cout() << "---------------- I waited to print! ----------------" << std::endl;
};
Timer t1{3'000, f};
Timer t2{6'000, f};
Timer t3{2'000, f};
Timer t4{1'000, f};
}
You create four Timer objects, each one having its own unique mutex object. So when t2 runs its thread, it locks its own mutex and it can because t1 locked a different mutex before beginning its loop.
I am using Boost Signals2 in one of our project.In this I want automatic connection management,for this I am testing Boost Signals2 tracking but I am not getting slot invoked.
After I run following code , slots are not called .
Environment:
VS 2010,windows 7,boost 1.54
#include <stdio.h>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/shared_ptr.hpp>
typedef boost::signals2::signal<void ()> signal_test;
using namespace boost;
class SubjectTest
{
public:
void Connect(const signal_test::slot_type &subscriber)
{
m_Signal.connect(subscriber);
std::cout << "No of connections : " << m_Signal.num_slots() << std::endl;
}
void Notify()
{
m_Signal();
}
private:
signal_test m_Signal;
};
class Listner
{
public:
Listner(){}
~Listner(){}
Listner(std::string name)
:m_name(name)
{
}
void GotSignal()
{
std::cout << m_name << std::endl;
}
void ConnectWithTracking(SubjectTest *s)
{
shared_ptr<Listner> l = new Listner();
s->Connect(signal_test::slot_type(&Listner::GotSignal,l.get()).track(l));
}
void ConnectNormal(SubjectTest *s)
{
s->Connect(bind(&Listner::GotSignal,this));
}
private:
std::string m_name;
shared_ptr<Listner> l;
};
void main()
{
Listner l2("First");
SubjectTest sub;
try
{
l2.ConnectWithTracking(&sub);
//l2.ConnectNormal(&sub);
sub.Notify();
{
Listner l3("Second");
l3.ConnectWithTracking(&sub);
//l3.ConnectNormal(&sub);
sub.Notify();
}
sub.Notify();
}
catch(std::exception ex)
{
std::cout << ex.what() << std::endl;
}
std::cout << "Finish" <<std::endl;
}
Updated :
*Working now*
#include <stdio.h>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/shared_ptr.hpp>
typedef boost::signals2::signal<void ()> signal_test;
using namespace boost;
class SubjectTest
{
public:
void Connect(const signal_test::slot_type &subscriber)
{
m_Signal.connect(subscriber);
std::cout << "No of connections : " << m_Signal.num_slots() << std::endl;
}
void Notify()
{
m_Signal();
}
private:
signal_test m_Signal;
};
class Listner : public boost::enable_shared_from_this<Listner>
{
public:
Listner(){}
~Listner(){}
Listner(std::string name)
:m_name(name)
{
}
void GotSignal()
{
std::cout << m_name << std::endl;
}
void ConnectWithTracking(SubjectTest *s)
{
s->Connect(signal_test::slot_type(&Listner::GotSignal,shared_from_this().get()).track(shared_from_this()));
}
void ConnectNormal(SubjectTest *s)
{
s->Connect(bind(&Listner::GotSignal,this));
}
private:
std::string m_name;
};
void main()
{
shared_ptr<Listner> l2(new Listner("First"));
SubjectTest sub;
try
{
l2->ConnectWithTracking(&sub);
sub.Notify();
{
shared_ptr<Listner> l3(new Listner("Second"));
l3->ConnectWithTracking(&sub);
//l3.ConnectNormal(&sub);
sub.Notify();
}
sub.Notify();
}
catch(std::exception ex)
{
std::cout << ex.what() << std::endl;
}
std::cout << "Finish" <<std::endl;
}
Now this is complete example of Signal2 Automatic Connection Management
{
shared_ptr<Listner> l(new Listner());
s->Connect(signal_test::slot_type(&Listner::GotSignal,l.get()).track(l));
}
In the above lines l pointee gets destroyed at the closing } - meaning that the slot you just connected got expired.
The whole point of tracking is to pass to track() a shared_ptr (or weak_ptr), which is bound (or tightly related) to the slot itself. It doesn't make sense to pass a shared_ptr whose lifespan is unrelated to that of the slot itself.
I have this:
catch (Except& e) {
std::cout << e.print() << std::endl;
}
I want this to print: OK you won!
so I have the class:
class Except{
public:
std::string print() {
std::string error("OK you won!\n");
return error;
}
};
I have this error in the Except class: "'string' in namespace 'std' does not name a type"
You have to include the header for std::string : #include <string>
You're probably not throwing it right - works for me:
#include <iostream>
#include <string>
class Except{
public:
std::string stack() {
std::string error("OK you won!\n");
return error;
}
};
int main() {
try {
throw Except();
} catch (Except& e) {
std::cout << e.stack() << std::endl;
}
return 0;
};
Output:
OK you won!
Check the code below:
#include <iostream>
#include <string>
class Except{
public:
std::string stack() {
std::string error("OK you won!\n");
return error;
}
};
int main() {
try {
throw Except();
} catch (Except &e) {
std::cout << e.stack() << std::endl;
}
return 0;
}
The output is:
./a.out
OK you won!