Reputation: 2341
I have a fairly generic work queue. It takes some number of std::function<void(void)>
and executes them on N worker threads. Closures + type erasure working well.
Now however, I would like the functions to "return" some state, and I would prefer the queue know nothing about what the types might be. To that end, I am considering using a queue of
std::function <std::function<void(void)>(void)>
Which, if I can keep the syntax straight, is a function taking void and returning a function taking void and returning void. The idea being to add a second work queue to return the result of the task execution.
This doesn't strictly solve the problem though - I can then call the returned value, but this doesn't obviously allow me to retrieve the state.
I could return boost::any, which doesn't appear to tell me what the contained type is, or boost::variant which means providing the task library with a list of all possible return types. Neither seem ideal.
What I would like to do is encode the information required to interpret the result of the function call within the functor, but I do not see a clean way to achieve this. Bundling an execute() and an extract() method into a single void(void) functor is beyond my cunning.
An alternative workaround is a heterogenous work queue, but such a thing is also quite a pain to write in C++. I feel optimistic that there is an idiomatic solution for getting at the unknown type that results from executing type erased code, but guessing the search keywords has not gone well for me. Guidance would be appreciated.
edit: An outline of the intended workflow for the application code, as distinct from the work queue / thread pool layer
std::function</*consistent type*/>
edit: As suggested in the comments, type erasure goes both ways. Let the generic functor be:
struct functor
{
typedef std::function<void(void)> functype;
functype async;
functype result;
};
Then use an instance of queue<functor>
for both send and receive. Async gets run on a remote thread. When an instance of functor comes back we have no idea what it represents, but the result() member does and can perform whatever next step is considered reasonable. This will probably suffice.
Upvotes: 1
Views: 171
Reputation: 96241
(Copying from my comment):
Instead of having step 6
know the precise concrete type, what about solving your problem by using either dynamic or static polymorphism instead?
Upvotes: 1