How can I check if thread is done, when using thread::detach - c++

I am trying to make kind of "running check" to avoid running one function multiple times at once it is for my another project. I have to use while() and detach() , the problem is I don't really know how can I check if thread is joinable(), because when I am not doing this this, the error comes out: Unhandled exception at 0x7632A842 in dasd.exe: Microsoft C++ exception: std::system_error at memory location 0x009BF614. but when I use code below I am getting no errors, but loop won't work
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
using namespace std::chrono_literals;
void Thing()
{
std::this_thread::sleep_for(3s);
std::cout << "done\n";
}
int main()
{
std::packaged_task<void()> task(Thing);
auto future = task.get_future();
std::thread ac(std::move(task));
while (true)
{
std::cout << ac.joinable() << std::endl;
if (future.wait_for(1ms) == std::future_status::ready && ac.joinable())
{
ac.detach();
std::cout << "good\n";
}
std::this_thread::sleep_for(1s);
}
}
the output is:
1
1
1
done
1
good
0
0
.......
the question is: how can i make successful loop avoiding errors? I am trying for such as long time, and i think it is about something what i just don't know...
Thank You in advance

Don't detach().
People use detach() far, far too often.
It should only be used in relatively rare circumstances. A thread running after the end of main is not a good idea, and without formal synchronization with the end of the thread, preventing that is basically impossible.
There are two ways to do this with a detach()ed thread -- the _at_thread_exit methods of std::promise, or using OS-specific APIs.
A thread pool might be what you want.
template<class T>
struct threadsafe_queue {
std::optional<T> try_pop();
T wait_and_pop();
void push(T);
std::deque<T> pop_all();
private:
mutable std::mutex m;
std::condition_variable cv;
std::deque<T> data;
};
struct thread_pool {
explicit thread_pool( std::size_t number_of_threads );
std::size_t thread_count() const;
void add_thread(std::size_t n=1);
void abort_all_tasks_and_threads();
void wait_for_empty_queue();
~thread_pool();
template<class F>
std::future<std::invoke_result_t<F>> add_task( F f );
private:
using task=std::future<void()>; // or std::packaged_task<void> or something custom
std::vector<std::thread> threads;
threadsafe_queue< task > tasks;
};
something vaguely like that.
Then make a 1 thread thread-pool, and shove tasks into that.

Related

Guarded thread C++

I'm trying to create a "guarded_thread", but I receive an error 'operator=' is a private member of 'std::__1::thread'. Here is my code:
struct guarded_thread : std::thread{
using std::thread::thread;
using std::thread::operator=;
~guarded_thread(){if(joinable())join();}
};
A function did the work, but I want to know how to create it the other way
void Guarded_thread(std::thread &Thread){
if (Thread.joinable()) {
Thread.join();
}
}
std::threads destructor is not virtual. Hence, you won't get to use your guarded_thread polymorphically and there is little benefit of inheritance compared to making the thread a member. std::thread cannot be copied, thats basically what the error says, so guarded_thread cannot be copied as well. Though, it can be moved:
#include <thread>
#include <iostream>
struct guarded_thread {
std::thread t;
~guarded_thread() {
if(t.joinable()) {
t.join();
}
}
};
void foo(guarded_thread&& t) {}
int main() {
foo(guarded_thread{ std::thread{ [](){ std::cout << "hello world"; }}});
}
Live Demo
PS: std::thread not joining in its destructor was a surprise for many, and maybe also driven by that C++20 introduced std::jthread. As pointed out in a comment by Swift, std::jthreads destructor also request_stop()s the thread before joining it, while guarded_thread blocks forever when the thread runs infinitely.

Terminate loop in Thread on Member Change within Class

I have a class that runs a loop on a seperate thread and I want it to break when I change the value of a member to false:
#include <iostream>
#include <thread>
#include <future>
#include <chrono>
#include <functional>
#include <atomic>
class A
{
public:
void ChangeLoop(){
loop = !loop;
if(loop){
std::future<void> fi = std::async(std::launch::async, &A::RunLoop, this, std::ref(loop));
}
}
void RunLoop(std::atomic<bool> &loop_ref){
while(loop_ref){
emit(loop_ref);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
private:
std::atomic<bool> loop {false};
std::mutex emit_mutex;
template<class...Ts> void emit(Ts&&...ts){
auto lock = std::unique_lock<std::mutex>(emit_mutex);
using expand = int[];
void(expand{
0,
((std::cout << ts << "\n"), 0)...
});
}
};
int main(){
A a;
a.ChangeLoop();
std::this_thread::sleep_for(std::chrono::seconds(2));
a.ChangeLoop();
return 0;
}
When I change loop to false, the thread does not break as I would expect. Alternatively, I tried to have the threaded function look at the member variable without taking any arguments, but had the same issue:
#include <iostream>
#include <thread>
#include <future>
#include <chrono>
#include <functional>
#include <atomic>
class A
{
public:
void ChangeLoop(){
loop = !loop;
if(loop){
std::future<void> fi = std::async(std::launch::async, &A::RunLoop, this);
}
}
void RunLoop(){
while(loop){
emit(loop);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
private:
std::atomic<bool> loop {false};
std::mutex emit_mutex;
template<class...Ts> void emit(Ts&&...ts){
auto lock = std::unique_lock<std::mutex>(emit_mutex);
using expand = int[];
void(expand{
0,
((std::cout << ts << "\n"), 0)...
});
}
};
int main(){
A a;
a.ChangeLoop();
std::this_thread::sleep_for(std::chrono::seconds(2));
a.ChangeLoop();
return 0;
}
How can I thread my RunLoop function seperately, and have it break when I change member variable loop?
As you have already found the working solution to your problem, I just want to point out why std::async is the not the right choice here.
From the online reference on std::async:
If the std::future obtained from std::async is not moved from or bound to a reference, the destructor of the std::future will block at the end of the full expression until the asynchronous operation completes.
So what you have here is the destructor of std::future blocking because the thread with RunLoop never completes execution because of its while loop.
This is true even when the return value from std::async is ignored in ChangeLoop and not assigned to a std::future.
Some C++ experts say that an std::future produced by std::async should not block. Here is an article by Herb Sutter where he argues this.
But for now the solution proposed in the comment (of using std::detach) is the way to go.

std::promise external code, async cancellation

Suppose you have some external synchronous code you cannot modify, and you require it to run async but also require it to be cancellable. If the external code is blocking then I have two options.
A) Fool the user and let my async method return immediately on cancellation, well aware that the code is still running to completion somewhere.
B) Cancel execution
I would like to implement an interface for option B
namespace externallib {
std::uint64_t timeconsuming_operation()
{
std::uint64_t count = 0;
for (auto i = 0; i < 1E+10; ++i)
{
count++;
}
return count;
}
}
template <typename R>
struct async_operation
{
struct CancelledOperationException
{
std::string what() const
{
return what_;
}
private:
std::string what_{ "Operation was cancelled." };
};
template<typename Callable>
async_operation(Callable&& c)
{
t_ = std::thread([this, c]()
{
promise_.set_value(c()); // <-- Does not care about cancel(), mostly because c() hasn't finished..
});
}
std::future<R> get()
{
return promise_.get_future();
}
void cancel()
{
promise_.set_exception(std::make_exception_ptr(CancelledOperationException()));
}
~async_operation()
{
if (t_.joinable())
t_.join();
}
private:
std::thread t_;
std::promise<R> promise_;
};
void foo()
{
async_operation<std::uint64_t> op([]()
{
return externallib::timeconsuming_operation();
});
using namespace std::chrono_literals;
std::this_thread::sleep_for(5s);
op.cancel();
op.get();
}
In the code above I cannot wrap my head around the limitation of external code being blocking, how, if at all, is it possible to cancel execution early?
Short answer:
Don't cancel/terminate thread execution unless it is mission critical. Use approach "A" instead.
Long answer:
As #Caleth noted, there is no standard nor cross platform way to do this. All you can do is to get a native handle to a thread and use platform specific function. But there are some important pit falls.
win32
You may terminate a thread with TerminateThread function, but:
stack variables will not be destructed
thread_local variables will not be destructed
DLLs will not be notified
MSDN says:
TerminateThread is a dangerous function that should only be used in
the most extreme cases.
pthread
Here situation is slightly better. You have a chance to free your resources when pthread_cancel is got called, but:
By default, target thread terminates on cancellation points. It means that you cannot cancel a code that doesn't have any cancellation point. Basically, for(;;); won't be canceled at all.
Once cancellation point is reached, implementation specific exception is thrown, so resources can be gracefully freed.
Keep in mind, that this exception can be caught by try/catch, but it's required to be re-thrown.
This behavior can be disabled by pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, nullptr);. But in case cancellation point is not met, resources won't be freed (as for win32)
Example
#include <iostream>
#include <thread>
#include <chrono>
#if defined(_WIN32)
#include <Windows.h>
void kill_thread(HANDLE thread) {
TerminateThread(thread, 0);
}
#else
#include <pthread.h>
void kill_thread(pthread_t thread) {
pthread_cancel(thread);
}
#endif
class my_class {
public:
my_class() { std::cout << "my_class::my_class()" << std::endl; }
~my_class() { std::cout << "my_class::~my_class()" << std::endl; }
};
void cpu_intensive_func() {
#if !defined(_WIN32)
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, nullptr);
#endif
my_class cls;
for(;;) {}
}
void io_func() {
my_class cls;
int a;
std::cin >> a;
}
void io_func_with_try_catch() {
my_class cls;
try {
int a;
std::cin >> a;
} catch(...) {
std::cout << "exception caught!" << std::endl;
throw;
}
}
void test_cancel(void (*thread_fn) (void)) {
std::thread t(thread_fn);
std::this_thread::sleep_for(std::chrono::seconds(1));
kill_thread(t.native_handle());
t.join();
std::cout << "thread exited" << std::endl;
std::cout << "--------------------" << std::endl;
}
int main() {
test_cancel(cpu_intensive_func);
test_cancel(io_func);
test_cancel(io_func_with_try_catch);
return 0;
}
You may see that:
The destructor is never called on windows.
Removing of pthread_setcanceltype leads to hang.
The internal pthread exception could be caught.
There is no portable way to end a thread before it wants to.
Depending on your platform, there may be ways of ending a thread, which you will probably need to get std::thread::native_handle to utilise. This is highly likely to lead to undefined behaviour, so I don't recommend it.
You can run that external synchronous code in another process and terminate that entire process. This way the interruption won't affect your process and cause undefined behaviour.

Use Boost strand in conjunction with std::future

I have come across a use case where I would like to use a Boost strand in conjunction with a std::future.
To reduce code duplication, I have written a generic function which will post a task to a boost strand and return the future.
// Some definitions first...
typedef boost::asio::io_service::strand cb_strand;
typedef std::shared_ptr< cb_strand > cb_strand_ptr;
The code looks something like:
//////////////////////////////////////////////////////////////////////////
template <class Task>
auto post_future_to_strand(cb_strand_ptr apStrand, Task task)
{
using return_type = decltype(task());
auto promise = std::make_shared<std::promise<return_type>>();
auto future = promise->get_future();
apStrand->wrap
(
[promise, task]()
{
try
{
promise->set_value(task());
}
catch (...)
{
// LOG ERROR ...
// NOTE: Exceptions can be thrown when setting the exception!
try
{
promise->set_exception(std::current_exception());
}
catch (...)
{
//LOG ERROR ...
}
}
}
);
return future;
};
I then hoped to post a future to a strand as presented in the following example:
std::future<int> f = post_future_to_strand(m_apStrand, std::bind(&foo::bar, this))
std::cout << "foo::bar() -> int is " << f.get() << std::endl;
Unfortunately, I get a runtime exception:
terminate called after throwing an instance of 'std::future_error'
what(): std::future_error: Broken promise
Signal: SIGABRT (Aborted)
Having read the docs, I think I understand what a broken promise is and how the situation arises; however, I feel like I am capturing the promise in the lambda so all should be well. I am a newcomer to this world of lambdas, so perhaps my understanding is amiss.
Ubuntu Zesty
GCC 6.3 (configured for C++14 with cmake)
You wrap the task, but you never post it. Therefore, the wrapped task is immediately destructed, and with that the promise.
There's another pitfall, things only work if you run the io_service on a different thread than the one blocking for the future... Otherwise you have created a deadlock:
Live On Coliru deadlock
Now that you have multiple threads, you need to avoid the race-condition where the service exits before the task is posted in the first place.
Bonus:
I'd suggest a far simpler take on the wrapper:
template <typename Task>
auto post_future_to_strand(cb_strand_ptr apStrand, Task task)
{
auto package = std::make_shared<std::packaged_task<decltype(task())()> >(task);
auto future = package->get_future();
apStrand->post([package] { (*package)(); });
return future;
}
Full Demo
Live On Coliru
#include <boost/asio.hpp>
#include <future>
#include <iostream>
using cb_strand_ptr = boost::asio::strand*;
//////////////////////////////////////////////////////////////////////////
template <typename Task>
auto post_future_to_strand(cb_strand_ptr apStrand, Task task)
{
auto package = std::make_shared<std::packaged_task<decltype(task())()> >(task);
auto future = package->get_future();
apStrand->post([package] { (*package)(); });
return future;
}
struct Foo {
boost::asio::strand s;
cb_strand_ptr m_apStrand = &s;
Foo(boost::asio::io_service& svc) : s{svc} {}
void do_it() {
std::future<int> f = post_future_to_strand(m_apStrand, std::bind(&Foo::bar, this));
std::cout << "foo::bar() -> int is " << f.get() << std::endl;
}
int bar() {
return 42;
}
};
int main() {
boost::asio::io_service svc;
auto lock = std::make_unique<boost::asio::io_service::work>(svc); // prevent premature exit
std::thread th([&]{ svc.run(); });
Foo foo(svc);
foo.do_it();
lock.reset(); // allow service to exit
th.join();
}
Prints
foo::bar() -> int is 42

C++ Concurrency segfault on mutex

Hello,
i am quite new to C++ but I have 6 years Java experience, 2 years C experience and some knowledge of concurrency basics. I am trying to create a threadpool to handle tasks. it is below with the associated test main.
it seems like the error is generated from
void ThreadPool::ThreadHandler::enqueueTask(void (*task)(void)) {
std::lock_guard<std::mutex> lock(queueMutex);
as said by my debugger, but doing traditional cout debug, i found out that sometimes it works without segfaulting and removing
threads.emplace(handler->getSize(), handler);
from ThreadPool::enqueueTask() improves stability greatly.
Overall i think it is related too my bad use of condition_variable (called idler).
compiler: minGW-w64 in CLion
.cpp
#include <iostream>
#include "ThreadPool.h"
ThreadPool::ThreadHandler::ThreadHandler(ThreadPool *parent) : parent(parent) {
thread = std::thread([&]{
while (this->parent->alive){
if (getSize()){
std::lock_guard<std::mutex> lock(queueMutex);
(*(queue.front()))();
queue.pop_front();
} else {
std::unique_lock<std::mutex> lock(idlerMutex);
idler.wait(lock);
}
}
});
}
void ThreadPool::ThreadHandler::enqueueTask(void (*task)(void)) {
std::lock_guard<std::mutex> lock(queueMutex);
queue.push_back(task);
idler.notify_all();
}
size_t ThreadPool::ThreadHandler::getSize() {
std::lock_guard<std::mutex> lock(queueMutex);
return queue.size();
}
void ThreadPool::enqueueTask(void (*task)(void)) {
std::lock_guard<std::mutex> lock(threadsMutex);
std::map<int, ThreadHandler*>::iterator iter = threads.begin();
threads.erase(iter);
ThreadHandler *handler = iter->second;
handler->enqueueTask(task);
threads.emplace(handler->getSize(), handler);
}
ThreadPool::ThreadPool(size_t size) {
for (size_t i = 0; i < size; ++i) {
std::lock_guard<std::mutex> lock(threadsMutex);
ThreadHandler *handler = new ThreadHandler(this);
threads.emplace(handler->getSize(), handler);
}
}
ThreadPool::~ThreadPool() {
std::lock_guard<std::mutex> lock(threadsMutex);
auto it = threads.begin(), end = threads.end();
for (; it != end; ++it) {
delete it->second;
}
}
.h
#ifndef WLIB_THREADPOOL_H
#define WLIB_THREADPOOL_H
#include <mutex>
#include <thread>
#include <list>
#include <map>
#include <condition_variable>
class ThreadPool {
private:
class ThreadHandler {
std::condition_variable idler;
std::mutex idlerMutex;
std::mutex queueMutex;
std::thread thread;
std::list<void (*)(void)> queue;
ThreadPool *parent;
public:
ThreadHandler(ThreadPool *parent);
void enqueueTask(void (*task)(void));
size_t getSize();
};
std::multimap<int, ThreadHandler*> threads;
std::mutex threadsMutex;
public:
bool alive = true;
ThreadPool(size_t size);
~ThreadPool();
virtual void enqueueTask(void (*task)(void));
};
#endif //WLIB_THREADPOOL_H
main:
#include <iostream>
#include <ThreadPool.h>
ThreadPool pool(3);
void fn() {
std::cout << std::this_thread::get_id() << '\n';
pool.enqueueTask(fn);
};
int main() {
std::cout << "Hello, World!" << std::endl;
pool.enqueueTask(fn);
return 0;
}
Your main() function invokes enqueueTask().
Immediately afterwards, your main() returns.
This gets the gears in motion for winding down your process. This involves invoking the destructors of all global objects.
ThreadPool's destructor then proceeds to delete all dynamically-scoped threads.
While the threads are still running. Hilarity ensues.
You need to implement the process for an orderly shutdown of all threads.
This means setting active to false, kicking all of the threads in the shins, and then joining all threads, before letting nature take its course, and finally destroy everything.
P.S. -- you need to fix how alive is being checked. You also need to make access to alive thread-safe, protected by a mutex. The problem is that the thread could be holding a lock on one of two differented mutexes. This makes this process somewhat complicated. Some redesign is in order, here.