Lifetime of std::promise and std::future - c++

My code:
void job_function(std::promise<void>& p) {
do_it();
p.set_value();
}
void foo() {
std::promise<void> p;
auto* thread = new std::thread(job_function, p);
p.get_future().wait_for(std::chrono::seconds(1));
}
In this code, if the calling thread of foo only waits for 1 second until the future completes. It is quite possible that the actual job gets completed after the wait is over. In this scenario, p is destructed already so call to p.set_value will not work. I can create p on heap, but even in that case it should be deleted and which thread should delete p depends on order of job completion and wait_for. Is there a specific pattern that can be used to handle this?

The trick is to move the promise into the thread and only keep the future around. Also, if you don't want to wait for the thread, detach it.
void job_function(std::promise<void> p) {
do_it();
p.set_value();
}
void foo() {
std::promise<void> p;
std::future<void> f = p.get_future();
std::thread thread(job_function, std::move(p));
thread.detach();
f.wait_for(std::chrono::seconds(1));
}

You are reimplementing std::packaged_task. Your code could be:
void job_function() {
do_it();
}
void foo() {
std::packaged_task<void(void)> task(job_function);
std::future result = task.get_future();
std::thread task_td(std::move(task));
result.wait_for(std::chrono::seconds(1));
}

shared_ptr to the rescue
void job_function(std::shared_ptr<std::promise> p) {
do_it();
p->set_value();
}
void foo() {
std::shared_ptr<std::promise> spPromise = std::make_shared<std::promise>();
auto* thread = new std::thread(job_function, spPromise);
spPromise->get_future().wait_for(std::chrono::seconds(1));
}
Now it doesn't matter if the thread completes before or after the original function that waits returns. The promise objects gets deleted when the last instance of the shared_ptr goes away.
If you want to keep the pass by reference semantics, just keep the shared_ptr captured by value for the lifetime of the thread.
void job_function(std::promise>& p) {
do_it();
p.set_value();
}
void foo() {
std::shared_ptr<std::promise> spPromise = std::make_shared<std::promise>();
std::promise& p = *spPromise.get();
auto* thread = new std::thread([spPromise] {
job_function(*spPromise.get()); // same as job_function(p)
});
p.get_future().wait_for(std::chrono::seconds(1));
}

Related

How to write multi-threaded functions inside a big function?

I have a function like this that is working fine:
void BigFunction()
{
void FunctionA(std::shared_ptr<ClassC> c);
}
now I want to add another function inside BigFunction()
void FunctionB(std::shared_ptr<ClassC> c);
which also take std::shared_ptr<ClassC> c as the input.
How do I do it correctly and safely so that both FunctionA() and FunctionB() can run in parallel, which means these two functions don't need to wait for each other and don't interfere with each other? Thanks.
Edit:
Here is the link of the code that I try but failed: https://onlinegdb.com/BJ5_BC0jI
You can use std::thread or std::future/std::async. For these "task"'s it is better/easier to use std::assync/future since the thread management is done for you.
bool func1(int a) {...}
bool func2(int a) {...}
void some_func()
{
std::future<bool> f1 = std::async(std::launch::async, func1, 1);
std::future<bool> f2 = std::async(std::launch::async, func1, 2);
bool res1 = f1.get(); // Only need this if you care about the result
bool res2 = f2.get(); // Only need this if you care about the result
}
If you don't care about the results you don't need that last two lines. But the .get() basically allows you to wait for your functions to finish. There are other options to do this... but its quite a general question...
Threads and lambda's:
bool func1(int a) {...}
bool func2(int a) {...}
void some_func()
{
std::thread t1 = []{ return func1(1); };
std::thread t2 = []{ return func2(2); };
// You must do this, otherwise your threads will go out of scope and std::terminate is called!
if (t1.joinable())
{
t1.join()
}
if (t2.joinable())
{
t2.join()
}
// Or instead of joining you can detach. But this is not recommend as you lose the ability to control your thread (left commented out as an example)
// t1.detach();
// t2.detach();
}
Update
Link to your "fixed" code: https://onlinegdb.com/S1hcwRAsL
Here is the code snippet for your convinience (and I am not sure if I have to save the changes! in GDB online!):
int main()
{
std::shared_ptr<classC> c = std::make_shared<classC>();
classB* b;
classA* a;
std::thread first([&b, &c]{ b->functionB(c); });
std::thread second([&a, &c]{ a->functionA(c); });
// synchronize threads:
first.join();
second.join();
std::cout << "A and B completed.\n";
return 0;
}

Thread-safe reference-counted queue C++

I'm struggling to implement a thread-safe reference-counted queue. The idea is that I have a number of tasks that each maintain a shared_ptr to a task manager that owns the queue. Here is a minimal implementation that should encounter that same issue:
#include <condition_variable>
#include <deque>
#include <functional>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
namespace {
class TaskManager;
struct Task {
std::function<void()> f;
std::shared_ptr<TaskManager> manager;
};
class Queue {
public:
Queue()
: _queue()
, _mutex()
, _cv()
, _running(true)
, _thread([this]() { sweepQueue(); })
{
}
~Queue() { close(); }
void close() noexcept
{
try {
{
std::lock_guard<std::mutex> lock(_mutex);
if (!_running) {
return;
}
_running = false;
}
_cv.notify_one();
_thread.join();
} catch (...) {
std::cerr << "An error occurred while closing the queue\n";
}
}
void push(Task&& task)
{
std::unique_lock<std::mutex> lock(_mutex);
_queue.emplace_back(std::move(task));
lock.unlock();
_cv.notify_one();
}
private:
void sweepQueue() noexcept
{
while (true) {
try {
std::unique_lock<std::mutex> lock(_mutex);
_cv.wait(lock, [this] { return !_running || !_queue.empty(); });
if (!_running && _queue.empty()) {
return;
}
if (!_queue.empty()) {
const auto task = _queue.front();
_queue.pop_front();
task.f();
}
} catch (...) {
std::cerr << "An error occurred while sweeping the queue\n";
}
}
}
std::deque<Task> _queue;
std::mutex _mutex;
std::condition_variable _cv;
bool _running;
std::thread _thread;
};
class TaskManager : public std::enable_shared_from_this<TaskManager> {
public:
void addTask(std::function<void()> f)
{
_queue.push({ f, shared_from_this() });
}
private:
Queue _queue;
};
} // anonymous namespace
int main(void)
{
const auto manager = std::make_shared<TaskManager>();
manager->addTask([]() { std::cout << "Hello world\n"; });
}
The problem I find is that on rare occasions, the queue will try to invoke its own destructor within the sweepQueue method. Upon further inspection, it seems that the reference count on the TaskManager hits zero once the last task is dequeued. How can I safely maintain the reference count without invoking the destructor?
Update: The example does not clarify the need for the std::shared_ptr<TaskManager> within Task. Here is an example use case that should illustrate the need for this seemingly unnecessary ownership cycle.
std::unique_ptr<Task> task;
{
const auto manager = std::make_shared<TaskManager>();
task = std::make_unique<Task>(someFunc, manager);
}
// Guarantees manager is not destroyed while task is still in scope.
The ownership hierarchy here is TaskManager owns Queue and Queue owns Tasks. Tasks maintaining a shared pointer to TaskManager create an ownership cycle which does not seem to serve a useful purpose here.
This is the ownership what is root of the problem here. A Queue is owned by TaskManager, so that Queue can have a plain pointer to TaskManager and pass that pointer to Task in sweepQueue. You do not need std::shared_pointer<TaskManager> in Task at all here.
I'd refactor the queue from the thread first.
But to fix your problem:
struct am_I_alive {
explicit operator bool() const { return m_ptr.lock(); }
private:
std::weak_ptr<void> m_ptr;
};
struct lifetime_tracker {
am_I_alive track_lifetime() {
if (!m_ptr) m_ptr = std::make_shared<bool>(true);
return {m_ptr};
}
lifetime_tracker() = default;
lifetime_tracker(lifetime_tracker const&) {} // do nothing, don't copy
lifetime_tracker& operator=(lifetime_tracker const&){ return *this; }
private:
std::shared_ptr<void> m_ptr;
};
this is a little utility to detect if we have been deleted. It is useful in any code that calls an arbitrary callback whose side effect could include delete(this).
Privately inherit your Queue from it.
Then split popping the task from running it.
std::optional<Task> get_task() {
std::unique_lock<std::mutex> lock(_mutex);
_cv.wait(lock, [this] { return !_running || !_queue.empty(); });
if (!_running && _queue.empty()) {
return {}; // end
}
auto task = _queue.front();
_queue.pop_front();
return task;
}
void sweepQueue() noexcept
{
while (true) {
try {
auto task = get_task();
if (!task) return;
// we are alive here
auto alive = track_lifetime();
try {
(*task).f();
} catch(...) {
std::cerr << "An error occurred while running a task\n";
}
task={};
// we could be deleted here
if (!alive)
return; // this was deleted, get out of here
}
} catch (...) {
std::cerr << "An error occurred while sweeping the queue\n";
}
}
}
and now you are safe.
After that you need to deal with the thread problem.
The thread problem is that you need your code to destroy the thread from within the thread it is running. At the same time, you also need to guarantee that the thread has terminated before main ends.
These are not compatible.
To fix that, you need to create a thread owning pool that doesn't have your "keep alive" semantics, and get your thread from there.
These threads don't delete themselves; instead, they return themselves to that pool for reuse by another client.
At shutdown, those threads are blocked on to ensure you don't have code running elsewhere that hasn't halted before the end of main.
To write such a pool without your inverted dependency mess, split the queue part of your code off. This queue owns no thread.
template<class T>
struct threadsafe_queue {
void push(T);
std::optional<T> pop(); // returns empty if thread is aborted
void abort();
~threadsafe_queue();
private:
std::mutex m;
std::condition_variable v;
std::deque<T> data;
bool aborted = false;
};
then a simple thread pool:
struct thread_pool {
template<class F>
std::future<std::result_of_t<F&()>> enqueue( F&& f );
template<class F>
std::future<std::result_of_t<F&()>> thread_off_now( F&& f ); // starts a thread if there aren't any free
void abort();
void start_thread( std::size_t n = 1 );
std::size_t count_threads() const;
~thread_pool();
private:
threadsafe_queue< std::function<void()> > tasks;
std::vector< std::thread > threads;
static void thread_loop( thread_pool* pool );
};
make a thread pool singleton. Get your threads for your queue from thread_off_now method, guaranteeing you a thread that (when you are done with it) can be recycled, and whose lifetime is handled by someone else.
But really, you should instead be thinking with ownership in mind. The idea that tasks and task queues mutually own each other is a mess.
If someone disposes of a task queue, it is probably a good idea to abandon the tasks instead of persisting it magically and silently.
Which is what my simple thread pool does.

Is it safe to wrap std::async in object

I wrapped std::async in a class similar to this:
class AsyncTask
{
public:
AsyncTask() {}
~AsyncTask()
{
m_shouldTerminate.store(true, std::memory_order::memory_order_release);
}
std::future<int> runAsync()
{
return std::async(std::launch::async, [this]() { threadMain(); return m_result; });
}
private:
void threadMain()
{
for(int i=0; i<std::numeric_limits<int>::max(); ++i)
{
if (m_shouldTerminate.load(std::memory_order::memory_order_acquire))
{
break;
}
// do time consuming calculation but abort if m_shouldTerminate becomes true
m_result += foo([this]() { return m_shouldTerminate.load(std::memory_order::memory_order_acquire); });
}
}
int m_result = 0;
std::atomic<bool> m_shouldTerminate = false;
};
AFAIK std::future::~future blocks if the future was returned from std::async. This would mean that for code like
{
AsyncTask myTask;
myTask.runAsync();
}
bar();
It would block in the temporary future's destructor, then destruct myTask and only then the call to bar() would happen. Considering this it should be ensured that the lifetime of any AsyncTask object exceeds the run time of the task itself and my implementation should be safe.
If AsyncTask is dynamically allocated this guarantee would no longer hold, obviously.
Are my assumptions correct an is my implementation safe? In particular is it possible that an AsyncTask object is destroyed while the async task is still running?

destroy thread's object from a joinable thread

struct Foo
{
boost::thread thread_;
void launchThread()
{
boost::thread(boost::bind(&Foo::worker, this));
}
void worker()
{
~Foo();
}
~Foo()
{
if (boost::this_thread::get_id() != thread_.get_id())
thread_.join();
}
};
In c++11 is it legal in a joinable thread to call the destructor of the class which declare the thread?
EDIT1, more realistic example:
struct Holder
{
std::unique_ptr<SocketClient> client_;
void ondisconnected(){client_.release();}
Holder()
{
//create SocketClient and launch the thread
}
}
struct SocketClient
{
boost::thread thread_;
void launchThread()
{
boost::thread(boost::bind(&SocketClient ::worker, this));
}
void worker()
{
run_ = true;
while (run_)
{
boost::system::error_code error;
auto receveidBytesCount = socket_.read_some(boost::asio::buffer(socketBuffer_), error);
if (error == boost::asio::error::eof)
{
disconnected_() // call Holder slot
return;
}
}
}
~SocketClient ()
{
run_ = false;
socket_.shutdown(boost::asio::socket_base::shutdown_both);
socket_.close();
if (boost::this_thread::get_id() == thread_.get_id())
thread_.detach();
else
thread_.join();
}
};
No. A joinable thread must be joined or detached before the thread object is destroyed. This will do neither if called from that thread. The thread's destructor will call terminate(), ending the program.
Whether it's acceptable to detach the thread depends on whether you're also destroying objects which the thread accesses. That rather depends on the large-scale design of your thread interactions, and can't really be answered in general.
Note that explicitly calling the destructor like that is almost certainly not valid; I assume that's just to illustrate that the destructor is being called (in a more suitable manner) on the thread.

Can I use std::async without waiting for the future limitation?

High level
I want to call some functions with no return value in a async mode without waiting for them to finish. If I use std::async the future object doesn't destruct until the task is over, this make the call not sync in my case.
Example
void sendMail(const std::string& address, const std::string& message)
{
//sending the e-mail which takes some time...
}
myResonseType processRequest(args...)
{
//Do some processing and valuate the address and the message...
//Sending the e-mail async
auto f = std::async(std::launch::async, sendMail, address, message);
//returning the response ASAP to the client
return myResponseType;
} //<-- I'm stuck here until the async call finish to allow f to be destructed.
// gaining no benefit from the async call.
My questions are
Is there a way to overcome this limitation?
if (1) is no, should I implement once a thread that will take those "zombie" futures and wait on them?
Is (1) and (2) are no, is there any other option then just build my own thread pool?
note:
I rather not using the option of thread+detach (suggested by #galop1n) since creating a new thread have an overhead I wish to avoid. While using std::async (at least on MSVC) is using an inner thread pool.
Thanks.
You can move the future into a global object, so when the local future's destructor runs it doesn't have to wait for the asynchronous thread to complete.
std::vector<std::future<void>> pending_futures;
myResonseType processRequest(args...)
{
//Do some processing and valuate the address and the message...
//Sending the e-mail async
auto f = std::async(std::launch::async, sendMail, address, message);
// transfer the future's shared state to a longer-lived future
pending_futures.push_back(std::move(f));
//returning the response ASAP to the client
return myResponseType;
}
N.B. This is not safe if the asynchronous thread refers to any local variables in the processRequest function.
While using std::async (at least on MSVC) is using an inner thread pool.
That's actually non-conforming, the standard explicitly says tasks run with std::launch::async must run as if in a new thread, so any thread-local variables must not persist from one task to another. It doesn't usually matter though.
why do you not just start a thread and detach if you do not care on joining ?
std::thread{ sendMail, address, message}.detach();
std::async is bound to the lifetime of the std::future it returns and their is no alternative to that.
Putting the std::future in a waiting queue read by an other thread will require the same safety mechanism as a pool receiving new task, like mutex around the container.
Your best option, then, is a thread pool to consume tasks directly pushed in a thread safe queue. And it will not depends on a specific implementation.
Below a thread pool implementation taking any callable and arguments, the threads do poling on the queue, a better implementation should use condition variables (coliru) :
#include <iostream>
#include <queue>
#include <memory>
#include <thread>
#include <mutex>
#include <functional>
#include <string>
struct ThreadPool {
struct Task {
virtual void Run() const = 0;
virtual ~Task() {};
};
template < typename task_, typename... args_ >
struct RealTask : public Task {
RealTask( task_&& task, args_&&... args ) : fun_( std::bind( std::forward<task_>(task), std::forward<args_>(args)... ) ) {}
void Run() const override {
fun_();
}
private:
decltype( std::bind(std::declval<task_>(), std::declval<args_>()... ) ) fun_;
};
template < typename task_, typename... args_ >
void AddTask( task_&& task, args_&&... args ) {
auto lock = std::unique_lock<std::mutex>{mtx_};
using FinalTask = RealTask<task_, args_... >;
q_.push( std::unique_ptr<Task>( new FinalTask( std::forward<task_>(task), std::forward<args_>(args)... ) ) );
}
ThreadPool() {
for( auto & t : pool_ )
t = std::thread( [=] {
while ( true ) {
std::unique_ptr<Task> task;
{
auto lock = std::unique_lock<std::mutex>{mtx_};
if ( q_.empty() && stop_ )
break;
if ( q_.empty() )
continue;
task = std::move(q_.front());
q_.pop();
}
if (task)
task->Run();
}
} );
}
~ThreadPool() {
{
auto lock = std::unique_lock<std::mutex>{mtx_};
stop_ = true;
}
for( auto & t : pool_ )
t.join();
}
private:
std::queue<std::unique_ptr<Task>> q_;
std::thread pool_[8];
std::mutex mtx_;
volatile bool stop_ {};
};
void foo( int a, int b ) {
std::cout << a << "." << b;
}
void bar( std::string const & s) {
std::cout << s;
}
int main() {
ThreadPool pool;
for( int i{}; i!=42; ++i ) {
pool.AddTask( foo, 3, 14 );
pool.AddTask( bar, " - " );
}
}
Rather than moving the future into a global object (and manually manage deletion of unused futures), you can actually move it into the local scope of the asynchronously called function.
"Let the async function take its own future", so to speak.
I have come up with this template wrapper which works for me (tested on Windows):
#include <future>
template<class Function, class... Args>
void async_wrapper(Function&& f, Args&&... args, std::future<void>& future,
std::future<void>&& is_valid, std::promise<void>&& is_moved) {
is_valid.wait(); // Wait until the return value of std::async is written to "future"
auto our_future = std::move(future); // Move "future" to a local variable
is_moved.set_value(); // Only now we can leave void_async in the main thread
// This is also used by std::async so that member function pointers work transparently
auto functor = std::bind(f, std::forward<Args>(args)...);
functor();
}
template<class Function, class... Args> // This is what you call instead of std::async
void void_async(Function&& f, Args&&... args) {
std::future<void> future; // This is for std::async return value
// This is for our synchronization of moving "future" between threads
std::promise<void> valid;
std::promise<void> is_moved;
auto valid_future = valid.get_future();
auto moved_future = is_moved.get_future();
// Here we pass "future" as a reference, so that async_wrapper
// can later work with std::async's return value
future = std::async(
async_wrapper<Function, Args...>,
std::forward<Function>(f), std::forward<Args>(args)...,
std::ref(future), std::move(valid_future), std::move(is_moved)
);
valid.set_value(); // Unblock async_wrapper waiting for "future" to become valid
moved_future.wait(); // Wait for "future" to actually be moved
}
I am a little surprised it works because I thought that the moved future's destructor would block until we leave async_wrapper. It should wait for async_wrapper to return but it is waiting inside that very function. Logically, it should be a deadlock but it isn't.
I also tried to add a line at the end of async_wrapper to manually empty the future object:
our_future = std::future<void>();
This does not block either.
You need to make your future a pointer. Below is exactly what you are looking for:
std::make_unique<std::future<void>*>(new auto(std::async(std::launch::async, sendMail, address, message))).reset();
Live example
i have no idea what i'm doing, but this seem to work:
// :( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3451.pdf
template<typename T>
void noget(T&& in)
{
static std::mutex vmut;
static std::vector<T> vec;
static std::thread getter;
static std::mutex single_getter;
if (single_getter.try_lock())
{
getter = std::thread([&]()->void
{
size_t size;
for(;;)
{
do
{
vmut.lock();
size=vec.size();
if(size>0)
{
T target=std::move(vec[size-1]);
vec.pop_back();
vmut.unlock();
// cerr << "getting!" << endl;
target.get();
}
else
{
vmut.unlock();
}
}while(size>0);
// ¯\_(ツ)_/¯
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
getter.detach();
}
vmut.lock();
vec.push_back(std::move(in));
vmut.unlock();
}
it creates a dedicated getter thread for each type of future you throw at it (eg. if you give a future and future, you'll have 2 threads. if you give it 100x future, you'll still only have 2 threads), and when there's a future you don't want to deal with, just do notget(fut); - you can also noget(std::async([]()->void{...})); works just fine, no block, it seems. warning, do not try to get the value from a future after using noget() on it. that's probably UB and asking for trouble.