Curious
Curious

Reputation: 21510

How C++11 threads are wrapped around pthreads

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

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

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

Related Questions