I want to create a thread pool for experimental purposes (and for the fun factor). It should be able to process a wide variety of tasks (so I can possibly use it in later projec
So the hard part is that packaged_task
is move-only, otherwise you could just toss it into a std::function
, and run those in your threads.
There are a few ways around this.
First, ridiculously, use a packaged_task
to store a packaged_task
. I'd advise against this, but it does work. ;) (what is the signature of operator()
on packaged_task
? What is the required signature for the objects you pass to packaged_task
?)
Second, wrap your packaged_task
in a shared_ptr
, capture that in a lambda with signature void()
, store that in a std::function
, and done. This has overhead costs, but probably less than the first solution.
Finally, write your own move-only function wrapper. For the signature void()
it is short:
struct task {
template,
class=decltype( std::declval()() )
>
task( F&& f ):
ptr(
new dF(std::forward(f)),
[](void* ptr){ delete static_cast(ptr); }
),
invoke([](void*ptr){
(*static_cast(ptr))();
})
{}
void operator()()const{
invoke( ptr.get() );
}
task(task&&)=default;
task&operator=(task&&)=default;
task()=default;
~task()=default;
explicit operator bool()const{return static_cast(ptr);}
private:
std::unique_ptr ptr;
void(*invoke)(void*) = nullptr;
};
and simple. The above can store packaged_task
for any type R
, and invoke them later.
This has relatively minimal overhead -- it should be cheaper than std::function
, at least the implementations I've seen -- except it does not do SBO (small buffer optimization) where it stores small function objects internally instead of on the heap.
You can improve the unique_ptr<> ptr
container with a small buffer optimization if you want.