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.
Related
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.
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.
Is it good or bad to create a thread in function object constructor by passing the dereferenced this pointer by reference to the thread object?
Is there any problem in below code?
Any improvement can be made on it to reach below objective?
The objective is to gracefully end the thread when the class object is out of scope.
#include <iostream>
#include <chrono>
#include <future>
#include <thread>
class MyThread {
private:
std::atomic<bool> exit;
std::thread t;
public:
MyThread() : exit(false) {
t = std::thread(std::ref(*this));
}
~MyThread() {
exit.store(true, std::memory_order_relaxed);
if (t.joinable()) {
t.join();
}
}
void operator()() {
while (!exit.load(std::memory_order_relaxed)) {
std::cout << "."; // some more meaningful work here
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
};
int main() {
MyThread t;
std::cin.get();
return 0;
}
It might work occasionally, but it's unsafe. It potentially generates a race condition, because you start the thread on an object that hasn't finished its construction yet, resulting in undefined behavior.
This is a code which works not as designed please explain me what is wrong here (code simplified to make this more readable).
shm_server server;
std::thread s{server};
// some work...
std::cout << "press any key to stop the server";
_getch();
server.stop();
s.join();
It looks like I call a stop method for another copy of shm_server class.
because stop() only sets std::atomic_bool done; (shm_server member) to true but I see that thread function (this is operator() of shm_server) still sees done equal to false.
std::thread has only move contructor?
How to send a signal to server correctly in this typical case?
class shm_server {
std::atomic_bool done;
public:
shm_server() : done{false} {}
shm_server(shm_server& ) : done{false} {}
void operator()() {
while (!done) {
//...
}
}
void stop() {
done = true;
}
};
You have somehow shot yourself into the foot by making shm_server copyable. I believe you did this in order to get rid of the compiler error, not because copy semantics on that class are particularly useful. I'd recommend you delete that constructor again. If you really want copy semantics, have the constructor take its argument by reference to const.
class shm_server // cannot copy or move
{
std::atomic_bool done_ {};
public:
void
operator()()
{
this->run();
}
void
run()
{
using namespace std::chrono_literals;
while (!this->done_.load())
{
std::clog << std::this_thread::get_id() << " working..." << std::endl;
std::this_thread::sleep_for(1ms);
}
}
void
stop()
{
this->done_.store(true);
}
};
I have factored out the logic of the call operator into a named function for convenience. You don't need to do that but I'll use it later in the example.
Now we somehow have to make the run member function be executed on its own thread. If you write
shm_server server {};
std::thread worker {server}; // won't compile
the compiler won't let you do it as it – as you have conjectured yourself – would attempt to copy the server object which isn't copyable.
#Ben Voigt has suggested to wrap the server object into a std::reference_wrapper which is an object that behaves like a reference.
shm_server server {};
std::thread worker {std::ref(server)};
This works as intended and effectively passes a pointer to the std::thread constructor, rather than the actual server object.
However, I find that this is not the most straight-forward solution here. What you really want to do is run a member function of your server on a different thread. And std::thread's constructor lets you do just that.
shm_server server {};
std::thread worker {&shm_server::run, &server};
Here, I'm passing the address of the run member function and a pointer to the server object (that will be passed as the implicit this pointer) as argument. I have introduced the run function since the syntax might be less irritating. You can also pass the address of the call operator directly.
shm_server server {};
std::thread worker {&shm_server::operator(), &server};
Here is a complete example.
int
main()
{
using namespace std::chrono_literals;
std::clog << std::this_thread::get_id() << " starting up" << std::endl;
shm_server server {};
std::thread worker {&shm_server::operator(), &server};
//std::thread worker {std::ref(server)}; // same effect
//std::thread worker {&shm_server::run, &server}; // same effect
std::this_thread::sleep_for(10ms);
server.stop();
worker.join();
std::clog << std::this_thread::get_id() << " good bye" << std::endl;
}
Possible output:
140435324311360 starting up
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435324311360 good bye
If you believe that a shm_server will only ever be useful if run on its own thread, you can also give it a std::thread as data member and have its constructor (or a dedicated start member function, if you prefer) start and its destructor join the thread.
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
class shm_server
{
std::atomic_bool done_ {};
std::thread worker_ {};
public:
shm_server()
{
this->worker_ = std::thread {&shm_server::run_, this};
}
~shm_server()
{
this->done_.store(true);
if (this->worker_.joinable())
this->worker_.join();
}
private:
void
run_()
{
using namespace std::chrono_literals;
while (!this->done_.load())
{
std::clog << std::this_thread::get_id() << " working..." << std::endl;
std::this_thread::sleep_for(1ms);
}
}
};
int
main()
{
using namespace std::chrono_literals;
std::clog << std::this_thread::get_id() << " starting up" << std::endl;
{
shm_server server {};
std::this_thread::sleep_for(10ms);
}
std::clog << std::this_thread::get_id() << " good bye" << std::endl;
}
Using C++, I would like to start a thread from a void method and then return before the thread may have finished. For example:
#include <thread>
using namespace std;
void longFunc(){
//stuff
}
void startThread(){
thread t(longFunc);
}
int main(void){
startThread();
//lots of stuff here...
return 0;
}
When the startThread() finishes, t tries to be deleted, and fails. How can I do this?
If you really want a fire-and-forget pattern, you can just detach from the thread:
void startThread(){
thread t(longFunc);
t.detach();
}
Or if you need to join the thread (which is most often a reasonable thing), you could simply return an std::thread object by value (thread wrappers are moveable):
std::thread startThread()
{
return std::thread(longFunc);
}
Anyway, you may consider launching the thread through std::async() and returning a future object instead. This would be exception-safe, since exceptions thrown in the launched thread will be swallowed by the future object, and thrown again in the main thread when you invoke get() on it:
#include <thread>
#include <future>
void longFunc()
{
//stuff
}
std::future<void> startThread()
{
return std::async(std::launch::async, longFunc);
}
int main(void)
{
auto f = startThread();
//lots of stuff here...
// For joining... (wrap in a try/catch block if you are interested
// in catching possible exceptions)
f.get();
}