C++Common std::make_unique, std::packaged_task and std::promise Problem - c++

The Problem
When creating schedulers the last copy or move of a function object is the last place that the function object is ever referenced (by a worker thread). If you were to use a std::function to store functions in the scheduler then any std::promises or std::packaged_task or other similarly move only types don't work as they cannot be copied by std::function.
Similarly, if you were to use std::packaged_task in the scheduler it imposes unnecessary overhead as many tasks do not require the std::future returned by packaged task at all.
The common and not great solution is to use a std::shared_ptr<std::promise> or a std::shared_ptr<std::packaged_task> which works but it imposes quite a lot of overhead.
The solution
A make_owner, similar to make_unique with one key difference, a move OR copy simply transfers control of destruction of the object. It is basically identical to std::unique_ptr, except that it is copyable (it basically always moves, even on a copy). Grosss....
This means that moving of std::functions doesn't require copies of the std::shared_ptr which require reference counting and it also means there is significantly less overhead on the reference counting etc. A single atomic pointer to the object would be needed and a move OR copy would transfer control. The major difference being that copy also transfers control, this might be a bit of a no-no in terms of strict language rules but I don't see another way around it.
This solution is bad because:
It ignores copy symantics.
It casts away const (in copy constructor and operator =)
Grrr
It isn't as nice of a solution as I'd like so if anybody knows another way to avoid using a shared pointer or only using packaged_tasks in a scheduler I'd love to hear it because I'm stumped...
I am pretty unsatisfied with this solution.... Any ideas?
I am able to re-implement std::function with move symantics but this seems like a massive pain in the arse and it has its own problems regarding object lifetime (but they already exist when using std::function with reference capture).
Some examples of the problem:
EDIT
Note in the target application I cannot do std::thread a (std::move(a)) as the scheduler threads are always running, at most they are put in a sleep state, never joined, never stopped. A fixed number of threads are in the thread pool, I cannot create threads for each task.
auto proms = std::make_unique<std::promise<int>>();
auto future = proms->get_future();
std::thread runner(std::move(std::function( [prom = std::move(proms)]() mutable noexcept
{
prom->set_value(80085);
})));
std::cout << future.get() << std::endl;
std::cin.get();
And an example with a packaged_task
auto pack = std::packaged_task<int(void)>
( []
{
return 1;
});
auto future = pack.get_future();
std::thread runner(std::move(std::function( [pack = std::move(pack)]() mutable noexcept
{
pack();
})));
std::cout << future.get() << std::endl;
std::cin.get();
EDIT
I need to do this from the context of a scheduler, I won't be able to move to the thread.
Please note that the above is minimum re-producible, std::async is not adequate for my application.

The main question is: Why you want to wrap a lambda with std::function before passing it to the std::thread constructor?
It is perfectly fine to do this:
std::thread runner([prom = std::move(proms)]() mutable noexcept
{
prom->set_value(80085);
});
You can find the explanation of why std::function does not allow you to store a move-only lambda here.
If you were going to pass std::function with wrapped lambda to some function, instead of:
void foo(std::function<void()> f)
{
std::thread runner(std::move(f));
/* ... */
}
foo(std::function<void()>([](){}));
You can do this:
void foo(std::thread runner)
{
/* ... */
}
foo(std::thread([](){}));
Update: It can be done in an old-fashioned way.
std::thread runner([prom_deleter = proms.get_deleter(), prom = proms.release()]() mutable noexcept
{
prom->set_value(80085);
// if `proms` deleter is of a `default_deleter` type
// the next line can be simplified to `delete prom;`
prom_deleter(prom);
});

Related

Do objects captured by a lambda exist for as long as the lambda?

I have always assumed lambda were just function pointers, but I've never thought to use capture statements seriously...
If I create a lambda that captures by copy, and then move that lambda to a completely different thread and make no attempt to save the original objects used in the lambda, will it retain those copies for me?
std::thread createThread() {
std::string str("Success");
auto func = [=](){
printf("%s", str.c_str());
};
str = "Failure";
return std::thread(func);
}
int main() {
std::thread thread = createThread();
thread.join();
// assuming the thread doesn't execute anything until here...
// would it print "Success", "Failure", or deference a dangling pointer?
return 0;
}
It is guaranteed to print Success. Capture-by-copy does exactly what it says. It make a copy of the object right there and stores this copy as part of the closure object. The member of the closure object created from the capture lives as long as the closure object itself.
A lambda is not a function pointer. Lambdas are general function objects that can have internal state, which a function pointer can't have. In fact, only capture-less lambdas can be converted to function pointers and so may behave like one sometimes.
The lambda expression produces a closure type that basically looks something like this:
struct /*unnamed1*/ {
/*unnamed1*/(const /*unnamed1*/&) = default;
/*unnamed1*/(/*unnamed1*/&&) = default;
/*unnamed1*/& operator=(const /*unnamed1*/&) = delete;
void operator()() const {
printf("%s", /*unnamed2*/.c_str());
};
std::string /*unnamed2*/;
};
and the lambda expression produces an object of this type, with /*unnamed2*/ direct-initialized to the current value of str. (Direct-initialized meaning as if by std::string /*unnamed2*/(str);)
You have 3 situations
You can be design guarantee that variables live longer then the thread, because you synchronize with the end of the thread before variables go out of scope.
You know your thread may outlive the scope/life cycle of your thread but you don't need access to the variables anymore from any other thread.
You can't say which thread lives longest, you have multiple thread accessing your data and you want to extend the live time of your variables
In case 1. Capture by reference
In case 2. Capture by value (or you even use move) variables
In case 3. Make data shared, std::shared_ptr and capture that by value
Case 3 will extend the lifetime of the data to the lifetime of the longest living thread.
Note I prefer using std::async over std::thread, since that returns a RAII object (a future). The destructor of that will synchronize with the thread. So you can use that as members in objects with a thread and make sure the object destruction waits for the thread to finish.

How to keep alive a shared_ptr-object of which members are used in an asynchronous function?

Imagine the following code:
void async(connection *, std::function<void(void)>);
void work()
{
auto o = std::make_shared<O>();
async(&o->member, [] { do_something_else(); } );
}
async will, for example, start a thread using member of o which was passed as a pointer. But written like this when o is going out of scope right after async() has been called and it will be deleted and so will member.
How to solve this correctly and nicely(!) ?
Apparently one solution is to pass o to the capture list. Captures are guaranteed to not be optimized out even if not used.
async(&o->member, [o] { do_something_else(); } );
However, recent compilers (clang-5.0) include the -Wunused-lambda-capture in the -Wextra collection. And this case produces the unused-lambda-capture warning.
I added (void) o; inside the lamdba which silences this warning.
async(&o->member, [o] {
(void) o;
do_something_else();
});
Is there are more elegant way to solve this problem of scope?
(The origin of this problem is derived from using write_async of boost::asio)
Boost.Asio seems to suggest using enable_shared_from_this to keep whatever owns the "connection" alive while there are operations pending that use it. For example:
class task : std::enable_shared_from_this<task> {
public:
static std::shared_ptr<task> make() {
return std::shared_ptr<task>(new task());
}
void schedule() {
async(&conn, [t = shared_from_this()]() { t->run(); });
}
private:
task() = default;
void run() {
// whatever
}
connection conn;
};
Then to use task:
auto t = task::make();
t->schedule();
This seems like a good idea, as it encapsulates all the logic for scheduling and executing a task within the task itself.
I suggest that your async function is not optimally designed. If async invokes the function at some arbitrary point in the future, and it requires that the connection be alive at that time, then I see two possibilities. You could make whatever owns the logic that underlies async also own the connection. For example:
class task_manager {
void async(connection*, std::function<void ()> f);
connection* get_connection(size_t index);
};
This way, the connection will always be alive when async is called.
Alternatively, you could have async take a unique_ptr<connection> or shared_ptr<connection>:
void async(std::shared_ptr<connection>, std::function<void ()> f);
This is better than capturing the owner of connection in the closure, which may have unforeseen side-effects (including that async may expect the connection to stay alive after the function object has been invoked and destroyed).
Not a great answer, but...
It doesn't seem like there's necessarily a "better"/"cleaner" solution, although I'd suggest a more "self descriptive" solution might be to create a functor for the thread operation which explicitly binds the member function and the shared_ptr instance inside it. Using a dummy lambda capture doesn't necessarily capture the intent, and someone might come along later and "optimize" it to a bad end. Admittedly, though, the syntax for binding a functor with a shared_ptr is somewhat more complex.
My 2c, anyway (and I've done similar to my suggestion, for reference).
A solution I've used in a project of mine is to derive the class from enable_shared_from_this and let it leak during the asynchronous call through a data member that stores a copy of the shared pointer.
See Resource class for further details and in particular member methods leak and reset.
Once cleaned up it looks like the following minimal example:
#include<memory>
struct S: std::enable_shared_from_this<S> {
void leak() {
ref = this->shared_from_this();
}
void reset() {
ref.reset();
}
private:
std::shared_ptr<S> ref;
};
int main() {
auto ptr = std::make_shared<S>();
ptr->leak();
// do whatever you want and notify who
// is in charge to reset ptr through
// ptr->reset();
}
The main risk is that if you never reset the internal pointer you'll have an actual leak. In that case it was easy to deal with it, for the underlying library requires a resource to be explicitly closed before to discard it and I reset the pointer when it's closed. Until then, living resources can be retrieved through a proper function (walk member function of Loop class, still a mapping to something offered by the underlying library) and one can still close them at any time, therefore leaks are completely avoided.
In your case you must find your way to avoid the problem somehow and that could be a problem, but it mostly depends on the actual code and I cannot say.
A possible drawback is that in this case you are forced to create your objects on the dynamic storage through a shared pointer, otherwise the whole thing would break out and don't work.

Threaded unique_ptr in a loop

A variant of
std::unique_ptr in a loop - memory leaks
In this modified question, RunSimulation() is a member method.
I would like one of the unique_ptr objects (sim) in main() to expire within main() and the other object (r) sent outside main() to free up in RunSimulation(). Would be great if you can provide a working code.
class Result { public: int n; };
class Simulation
{
public:
void RunSimulation(std::unique_ptr<Result> result) {result->n = 0;}
};
void main()
{
boost::thread_group threads;
std::unique_ptr<Result> r;
std::unique_ptr<Simulation> sim = std::make_unique<Simulation>();
for (int i = 0; i < 10; i++)
{
r = std::unique_ptr<Result>(new Result);
//Erroneous lines:
//threads.create_thread(boost::bind(&Simulation::RunSimulation, boost::ref(sim), std::move(r)));
//threads.create_thread([&] {sim->RunSimulation(std::move(r)); });
}
threads.join_all();
}
Your attempt to pass the functor created by boost::bind to create_thread fails because of the reason I explained in my answer to your previous question.
The attempt with the lambda should compile, but it has a subtle bug that will cause undefined behavior. I may have mislead you with my earlier answer, but this is the reason posting an MCVE is so important. The small snippet you posted in your previous question doesn't show how you intend to use the code.
The problem with the lambda is that it only stores a reference to the unique_ptr. You don't transfer ownership until the call to RunSimulation executes, in other words, transfer of ownership only happens after the thread execution has begun. But by that time the for loop within main may have moved on to the next iteration, causing the Result held by the unique_ptr in the previous iteration to be deleted. Dereferencing the unique_ptr within RunSimulation then causes undefined behavior.
The way around this is to transfer ownership of the unique_ptr immediately to the lambda, and then have the lambda again transfer ownership in the call to RunSimulation. This following lambda expression does what you want
[&sim, r=std::move(r)] () mutable {
sim->RunSimulation(std::move(r));
}
To explain what's going on, the lambda is capturing sim by reference (&sim) and it's using C++14's lambda init capture to transfer ownership of r within main to an r that is member of the lambda (r=std::move(r)) (you can call the lambda's member r something else if you want). The lambda itself needs to be mutable because you need to have non-const access to the r data member so you can move it when calling RunSimulation.
Unfortunately, this is not the end of your problems. Calling create_thread with the above lambda still doesn't compile because according to the documentation, it requires the callable object to be copyable. Your lambda isn't copyable because it has a unique_ptr data member.
A workaround is to create a boost::thread and then add_thread it to the thread_group.
auto t = new boost::thread([&sim, r=std::move(r)] () mutable {
sim->RunSimulation(std::move(r));
});
threads.add_thread(t);
Note that I can't find any documentation on exception safety guarantees that add_thread makes. So it's possible if an exception occurs while add_thread attempts to add the new thread to the thread_group, your thread object might leak.
Live demo
Finally, I think you need to rethink your design. Presumably, the Result object is supposed to hold the simulation result. What's the point of having RunSimulation store that in Result if you cannot access that Result within main after the simulation has ended?
As I suggested in the comments of my previous answer, you should probably create a container of Results in main and pass references to the elements of those containers to RunSimulation.

Why does std::thread take function to run by rvalue?

There is one thing about std::thread which I don't understand:
why the constructor of std::thread takes function to run by rvalue?
I usually want to run a Functor with some members to another thread. Like this:
struct Function
{
void operator() ( /* some args */)
{
/* some code */
}
/* some members */
}
void run_thread()
{
Functor f( /* some data */);
std::thread thread(f, /* some data */);
/* do something and wait for thread to finish */
}
With current implementation of std::thread I must be sure my object is implementing move semantics. I don't get why cannot I pass it by reference.
Extra question is: what does it mean to refer to function by rvalue? Lambda expression?
In your run_thread method f is an auto variable. That means at the bottom of the scope f will be destroyed. You claim that you will "wait for the thread to finish" but the compiler/runtime system does not know that! It has to assume that f will be deleted, possibly before the thread that is supposed to call its method has a chance to start.
By copying (or moving) the f, the run time system gains control of the lifetime of its copy of f and can avoid some really nasty, hard to debug problems.
std::reference_wrapper will expose an operator() to the wrapped object. If you are willing to do the manual lifetime maintenance, std::thread t(std::ref(f)); will run f by reference.
Of course in your code, this induces undefined behaviour as you did not manage lifetimes properly.
Finally, note that raw thread is a poor "client code" tool. async is a touch better, but really you want a task queue with packaged_tasks and futures and condition variables. C++11 added enough threading support to write a decent threading system, but it provides primitives, not good "client code" tools.
In a toy program it may be enough.

How can I create a smart pointer that locks and unlocks a mutex?

I have a threaded class from which I would like to occasionally acquire a pointer an instance variable. I would like this access to be guarded by a mutex so that the thread is blocked from accessing this resource until the client is finished with its pointer.
My initial approach to this is to return a pair of objects: one a pointer to the resource and one a shared_ptr to a lock object on the mutex. This shared_ptr holds the only reference to the lock object so the mutex should be unlocked when it goes out of scope. Something like this:
void A::getResource()
{
Lock* lock = new Lock(&mMutex);
return pair<Resource*, shared_ptr<Lock> >(
&mResource,
shared_ptr<Lock>(lock));
}
This solution is less than ideal because it requires the client to hold onto the entire pair of objects. Behaviour like this breaks the thread safety:
Resource* r = a.getResource().first;
In addition, my own implementation of this is deadlocking and I'm having difficulty determining why, so there may be other things wrong with it.
What I would like to have is a shared_ptr that contains the lock as an instance variable, binding it with the means to access the resource. This seems like something that should have an established design pattern but having done some research I'm surprised to find it quite hard to come across.
My questions are:
Is there a common implementation of this pattern?
Are there issues with putting a mutex inside a shared_ptr that I'm overlooking that prevent this pattern from being widespread?
Is there a good reason not to implement my own shared_ptr class to implement this pattern?
(NB I'm working on a codebase that uses Qt but unfortunately cannot use boost in this case. However, answers involving boost are still of general interest.)
I'm not sure if there are any standard implementations, but since I like re-implementing stuff for no reason, here's a version that should work (assuming you don't want to be able to copy such pointers):
template<class T>
class locking_ptr
{
public:
locking_ptr(T* ptr, mutex* lock)
: m_ptr(ptr)
, m_mutex(lock)
{
m_mutex->lock();
}
~locking_ptr()
{
if (m_mutex)
m_mutex->unlock();
}
locking_ptr(locking_ptr<T>&& ptr)
: m_ptr(ptr.m_ptr)
, m_mutex(ptr.m_mutex)
{
ptr.m_ptr = nullptr;
ptr.m_mutex = nullptr;
}
T* operator ->()
{
return m_ptr;
}
T const* operator ->() const
{
return m_ptr;
}
private:
// disallow copy/assignment
locking_ptr(locking_ptr<T> const& ptr)
{
}
locking_ptr& operator = (locking_ptr<T> const& ptr)
{
return *this;
}
T* m_ptr;
mutex* m_mutex; // whatever implementation you use
};
You're describing a variation of the EXECUTE AROUND POINTER pattern, described by Kevlin Henney in Executing Around Sequences.
I have a prototype implementation at exec_around.h but I can't guarantee it works correctly in all cases as it's a work in progress. It includes a function mutex_around which creates an object and wraps it in a smart pointer that locks and unlocks a mutex when accessed.
There is another approach here. Far less flexible and less generic, but also far simpler. While it still seems to fit your exact scenario.
shared_ptr (both standard and Boost) offers means to construct it while providing another shared_ptr instance which will be used for usage counter and some arbitrary pointer that will not be managed at all. On cppreference.com it is the 8th form (the aliasing constructor).
Now, normally, this form is used for conversions - like providing a shared_ptr to base class object from derived class object. They share ownership and usage counter but (in general) have two different pointer values of different types. This form is also used to provide a shared_ptr to a member value based on shared_ptr to object that it is a member of.
Here we can "abuse" the form to provide lock guard. Do it like this:
auto A::getResource()
{
auto counter = std::make_shared<Lock>(&mMutex);
std::shared_ptr<Resource> result{ counter, &mResource };
return result;
}
The returned shared_ptr points to mResource and keeps mMutex locked for as long as it is used by anyone.
The problem with this solution is that it is now your responsibility to ensure that the mResource remains valid (in particular - it doesn't get destroyed) for that long as well. If locking mMutex is enough for that, then you are fine.
Otherwise, above solution must be adjusted to your particular needs. For example, you might want to have the counter a simple struct that keeps both the Lock and another shared_ptr to the A object owning the mResource.
To add to Adam Badura's answer, for a more general case using std::mutex and std::lock_guard, this worked for me:
auto A::getResource()
{
auto counter = std::make_shared<std::lock_guard<std::mutex>>(mMutex);
std::shared_ptr<Resource> ptr{ counter, &mResource} ;
return ptr;
}
where the lifetimes of std::mutex mMutex and Resource mResource are managed by some class A.