0

I'm worked on a CLIENT SERVER application with cpprestsdk and it works fine. Now i want to improve readability of my code (lots of .then() method) using co-routines. Using co_await the compiler,(on VC++2015 or VC++2017) will refactor the code in a "continuation" getting rid of .then statement. I try to undestand how co_await works but actually i don't have complete understanding. Generally speaking if i have a task and a continuation like this:

client1.request(methods::GET, addr).then([=](http_response response)
{
    printf("Response status code %u returned.\n", response.status_code());

    if (response.status_code() == status_codes::OK)
    {
        wstring output = response.extract_utf16string().get();
        wcout << output << endl;
    }
 }).wait();

it becomes easily

auto response = co_await client1.request(methods::GET, addr); 
printf("Response status code %u returned.\n", response.status_code()); 
if (response.status_code() == status_codes::OK) 
{ wstring output = response.extract_utf16string().get();
  wcout << output << endl; 
} 

The problem for me now is when i have cose like this:

 pplx::task UploadFileToHttpServerAsync()
 {
      using concurrency::streams::file_stream;
      using concurrency::streams::basic_istream;

      namespace some_namespace = web::http;


      // Open stream to file.
      wstring filePath = L"out.txt";
      return file_stream<unsigned char>::open_istream(filePath).then([=](pplx::task<basic_istream<unsigned char>> previousTask)
      {
          try
          {
               auto fileStream = previousTask.get();

               // Make HTTP request with the file stream as the body.
               http_client client(XMLReader::data.URL);

               return client.request(methods::POST, filePath, fileStream).then([fileStream](pplx::task<http_response> previousTask)
                   {

How to use co_await to refactor my code if i have return statement?

kenhero
  • 95
  • 2
  • 11

1 Answers1

0

The whole idea behind co_await and so forth is that you write your code as if it were synchronous.

If stream<unsigned char>::open_istream were a synchronous function, what would it return? It would return a basic_istream<unsigned char>. So that's what co_awaiting on it will return (assuming that co_await machinery exists for pplx::task):

wstring filePath = L"out.txt";
basic_istream<unsigned char> fileStream = co_await file_stream<unsigned char>::open_istream(filePath);

From there, you keep writing your code as if it were synchronous:

// Make HTTP request with the file stream as the body.
http_client client(XMLReader::data.URL);

Then, you do the co_await stuff, continuing to write your code as if it were perfectly synchronous:

auto response = co_await client.request(methods::POST, filePath, fileStream);

Then you handle the response as you presumably would have in your incomplete code.

The only reason that was a return statement to begin with was because that's how you do continuations manually. Each layer of continuations returns the next task to be continued in the chain, with task::then catching the task and continuing it.

With co_await, you don't need to bother. You just pretend you're writing synchronous code and let the compiler make it fast.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • static pplx::task> open_istream is asynchronous file streams. It's defined in filestream.h of cpprestsdk – kenhero Jun 22 '17 at 11:30
  • 1
    @kenhero: I'm aware of that. My point is that `co_await` makes it *appear* synchronous. It unpacks the returned `task` and extracts the value out of it, allowing the rest of your code to act on that value normally. – Nicol Bolas Jun 22 '17 at 13:23
  • ok,i understand so i have to rewrite my code like it was synchronous. – kenhero Jun 22 '17 at 16:48