4

This is a conceptual question on the asynchronous task feature of the C++ REST SDK (and maybe also a bit of a noob question).

In a basic application, I have a client and perform several requests, e.g. like

http_client client(U("whatever"));

for(int i=0; i<100; ++i)
{
    http_request request;
    //fill the request
    client.request(request).then([](http_response response) { /* do something*/});
}

(The foor-loop is just to indicate that the request is sent often, I don't really use it in my code).

Questions:

  • As far I understand, the asynchronous task library then handles those incoming requests in a parallel way -- meaning that not the main thread handles all tasks in an event-like fashion, but rather the library assigns the tasks to an underlying thread pool in some (--to me intransparent--) way. Did I get that correct?

  • If the previous view is correct, then is there any reason to combine the REST SDK with the multithreading capabilities of C++. For example, taking again the above loop, start 10 threads and in each one process 10 loop iterations. Does this makes sense or is it unnecessary?

  • Moreover, in general, are there any common patterns where one should combine the ppl-capabilities by the C++11 multithreading feature? Or is it safe to rely that the REST SDK and ppl under the hood get the job done better?

(Info: I've asked this question also on the cpprest discussion page. However, this forum seems to be not maintained anymore.)

davidhigh
  • 12,239
  • 1
  • 34
  • 64

1 Answers1

5

As far I understand, the asynchronous task library then handles those incoming requests in a parallel way -- meaning that not the main thread handles all tasks in an event-like fashion, but rather the library assigns the tasks to an underlying thread pool in some (--to me intransparent--) way. Did I get that correct?

Yes, in the REST SDK, they use a threadpool to launch the task continuation. on windows, they use the Windows API ThreadPool functions (CreateThreadPool, TrySubmitThreadpoolCallback etc.) . on Linux, they use the Boost one.

If the previous view is correct, then is there any reason to combine the REST SDK with the multithreading capabilities of C++. For example, taking again the above loop, start 10 threads and in each one process 10 loop iterations. Does this makes sense or is it unnecessary?

Completly unnecessery, the platform has its own thread pool.

Moreover, in general, are there any common patterns where one should combine the ppl-capabilities by the C++11 multithreading feature? Or is it safe to rely that the REST SDK and ppl under the hood get the job done better?

well, the whole idea of a task is to abstract away the use of threads. threads don't scale well when dealling with many parallel tasks. the conventional approach is to use a thread pool to not spawn a new thread for each new task.

ppl tasks gives you the possibility to handle asynchronous IO in more elegant way. you encapsulate the CPU bound tasks in ppl::task, in these tasks, you can spawn another async IO operations, and use ppl::task::then to continue doing CPU bound tasks when the async IO is finished.

the mechanism is a chain of task-> aync IO -> continuation task-> async IO ->task and so one. when the task launches an IO operation, the underlying thread pool moves on to the next task. when the async IO is finished, it queues the continuation task on the end of the thread pool tasks queue.

So no, you should not directly create any std::thread on you own. you do however, want to use syncrhonization objects like std::mutex if you task accesses any shread resource.

------------------------------------
A good bonus:
on VC++ with visual studio 2015 RTM and above, you can use await on tasks and get rid of the then:

http_client client(U("whatever"));

for(int i=0; i<100; ++i)
{
    http_request request;
    //fill the request
   auto response = await client.request(request);
   //do something with the response
}

---------------------------------------------------
A bad bonus:
with my experience with REST SDK, its performance is extremly poor, not something you'd expect from a C++ platform.

David Haim
  • 23,138
  • 3
  • 38
  • 70
  • Good answer, thank you! Two further questions: (i) what about load balancing? Say one request has a huge response and 99 have a small one. Does ppl handle this properly? (ii) follow-up: if I use async tasks in different std::threads, each thread will have its own thread pool, isn't it? ... and thus that could be used to implement a custom balancing? – davidhigh Mar 31 '16 at 17:11
  • (i) sort of. it depends on the underlying thread pool implementation. (ii) no, the platform has only one thread pool always – David Haim Mar 31 '16 at 17:21
  • Does that mean a custom load balancing is not possible? – davidhigh Mar 31 '16 at 17:25
  • another question: you're writing that the use of `std::mutex` or other synchronization objects is reasonable when shared ressources are accessed. Does this work exactly like in "normal" multithreading (i.e. `std::thread`-based)? Or are there some further things to consider? – davidhigh Mar 31 '16 at 23:21
  • Good to know. Do you have any references for that? -- as I'm searching the net for the whole day and can hardly find anything with respect to locks in casablanca. – davidhigh Apr 01 '16 at 20:01
  • well you can just read the task source code, it's in VS in the header `` . basically, a task is a sophisticated functor, nothing less – David Haim Apr 01 '16 at 20:04
  • by the way: feel free to answer my other question on roughly these things, http://stackoverflow.com/questions/36351259/c-using-standard-library-synchronization-tools-with-the-c-rest-sdk. I'd really like to get you another at least 25 points for your effort. – davidhigh Apr 01 '16 at 20:26
  • [Here](http://msdev.developer-works.com/article/29193969/VS11+Beta%3A+mixing+PPL+and+C%2B%2B11+concurrency) is the reference I was asking for three comments ago. – davidhigh Apr 01 '16 at 21:47