bool pop_if_present(Message*& pMessage)
NamedPipe* Pipe=new NamedPipe(PipeName);
printf("creating pipe "); fflush(stdout);
printf("reading pipe "); fflush(stdout);
printf("dispatching %s ",Command.c_str()); fflush(stdout);
and the body of the while loop looks like this
void operator()(Message* pMessage) const
printf("hello! "); fflush(stdout);
printf("receiving command ");
printf("sending result '%s' ",Result);
When I run the program, it listens on the pipe and the clients can properly send data to it, however, it seems that the body of the loop is never called. I get all the debug output for creating the pipe, reading the pipe, and dispatching the message. But I don't even get the "hello" printed from the body of the while loop.
No, parallel_while and its successor parallel_do won't work for you in the current design. The reason is that in your design returning false from pop_if_present seems a norm (though I might be wrong here), while for those algorithms it means the end of their initial feeding. For parallel_do, we made this nature more obvious as it is fed with a pair of iterators,a typical interface to a container.
I think tbb::pipeline might suit your needs better. You would have (at least) two stages, one for input and one for processing. In the input stage, you should have a loop waiting for data (like parallel_while, there should be the "end of input" notion for pipeline, and returning NULL from the input stage serves this purpose). The irregular nature of thedata requests dictates the need for backoff in the busy-waitloop, unless the Pipe->Read command blocks. Once you got the request you exit the input stage passing the data (via return) for further processing in the pipeline.
Though it might look like the same waiting trick will work in your parallel_while based implementation, Ithink the pipeline is better for you because of a few reasons:
A lowlight: so far, there is a known issue that worker threads could spin idle if the pipeline input stage is blocked waiting for data. But, the fix for the issue is ready and will be available in the next OSS developer release of TBB.
I edited the above post trying to make clarifications, but still this is not enough.
If the Pipe->Read blocks, certainly you don't need any loop (so disregard related parts of the post), and your design is fine for pipeline (except for required interface changes) but not for parallel_while due to the "showstopper reason" I explained above. In your testing, if you issued a number of requests (four, if I remember it right) you would see their processing started - but this is not what you want to get :)
I hope I was able to explain the reasons of the behavior you saw, and also to give you some perspective :)
What you have described is a known flaw in the "old" design of the pipeline (and I will explain why I called it "old"). In that design, nTokens items are taken out of input stage right after the pipeline started, and passed to stage 2. Of those, nThreads items pass stage 2. But after that, instead of processing the rest of items already taken from input, every worker wanted to take a new item from the input. Not a good idea, and besides, that wasthe reason of idle spinning because the input stage is always serial and if one worker is blocked there, all other workers spin idle in attempts to enter the input stage. In your case, if your input stage would return NULL at some moment, you would see the third item being processed after that. Again, not quite what you want.
The idle spinning issue was reported to us, and as I said, we have the fix ready for it. The good news for you is that the fix actually refactors that pipeline design (which I now call "old") with a much better one, and this issue with "hanging" items should go away as well; now no items are pre-taken from input, a worker only go for next item when it can't proceed with current items.
We plan to release the update this week or might be early next week, and it will contain the fix. Meanwhile, in current development releases, there is functionality to detect the default number of workers created by task_scheduler_init if no explicit number was given. Use task_scheduler_init::default_num_threads for it. Alas this function is not available in any com-aligned release.
Mike, it doesn't look like you'll have to wait long. A new development release was posted today, and includes pipeline performance improvements. I don't know if this contains everything Alexey discussed earlier in this thread, but the spin waiting has been removed, according to the CHANGES file