Reputation: 21510
So C++11 threads are wrappers around pthreads on most systems, I am confused how the syntax for going from a variadic function to a more strict function with a specified return type might work (i.e. the callback function with pthreads) can someone give an example that could illustrate the same?
Upvotes: 1
Views: 933
Reputation: 275220
Suppose you have a C style interface that looks like:
Foo run( Foo(*)(void*), void* );
And you want to write:
template<class F, class...Args>
std::result_of<F(Args...)>
smart_run( F&& f, Args&&... args );
This is analogous to what you need to do to implement std::thread
on top of pthreads. I simplified stuff a bit, because it is noise (no std ref support, no decaying, etc).
For the first step, take F
and Args...
and bind them up. Something like std::bind(f, args...)
that returns a zero-arg function that returns the result.
With that, we just need to solve:
template<class F>
std::result_of<F()>
smart_run( F&& f );
which takes an arbitrary callable, then uses run
above to run it.
The trick is to create a copy of f
on the free store and a function that calls it like this:
template<class F>
std::result_of<F()>
smart_run( F&& f ){
struct data{
F f;
std::result_of_t<F()> r;
};
data*p = new data{std::forward<F>(f)};
Foo ignored=run(
[](void* p){
data* self=static_cast<data*>(p);
auto& f=self->f;
self->r = f();
return Foo{}; // whatever
},
p
);
auto r=data->r;
delete data;
return r;
}
Now, the r is assigned instead of constructed. But the core of the idea -- that you pass the fancy callable in the void*
, andmthe function unwraps it and interacts with it, and done is there.
In a real thread on pthread, you'd pass a pointer-to-std::thread-state to the pthread invoker. It would set whatever up, invoke the stored procedure, and when done would take the return value and store it in the internal std::thread state (if needed). Then you could get that data by interacting with the internal std::thread state.
Or something else roughly equivalent.
Upvotes: 3