title: How to correctly use grpc asynchronously (ClientAsyncReaderWriter)
body: <p>I can't find a grpc example showing how to use the ClientAsyncReaderWriter <em>(is there one?)</em>.  I tried something on my own, but am having trouble with the reference counts.  My question comes from tracing through the code.</p>
  
  <p><a href="https://github.com/grpc/grpc/blob/3640b4084ac8485ef99ab3162cae7b8b079bbf6b/src/core/lib/surface/call.cc#L154" rel="nofollow noreferrer"><code>struct grpc_call</code></a> has a member of type <a href="https://github.com/grpc/grpc/blob/3640b4084ac8485ef99ab3162cae7b8b079bbf6b/src/core/lib/surface/call.cc#L154" rel="nofollow noreferrer"><code>gpr_refcount</code></a> called <code>ext_ref</code>.  The ClientContext C++ object wraps the grpc_call, and holds onto it in a member <a href="https://github.com/grpc/grpc/blob/3640b4084ac8485ef99ab3162cae7b8b079bbf6b/include/grpc%2B%2B/impl/codegen/client_context.h#L394" rel="nofollow noreferrer"><code>grpc_call *call_;</code></a>.  Only when ext_ref is 0, can this grpc_call pointer be deleted.</p>
  
  <p><strong>When I use grpc synchronously with <a href="https://grpc.io/grpc/cpp/classgrpc_1_1_client_reader_writer.html" rel="nofollow noreferrer">ClientReader</a>:</strong></p>
  
  <ul>
  <li>In its implementation it uses CreateCall() and PerformOps() to add to ext_ref (<code>ext_ref == 2</code>).  </li>
  <li>Then I use Pluck() which subtracts from ext_ref so that (<code>ext_ref == 1</code>).</li>
  <li>The last use ~ClientContext() subtracts from ext_ref, so that <code>ext_ref == 0</code> and deletes the call</li>
  </ul>
  
  <p><strong>But when I use grpc asynchronously with <a href="https://grpc.io/grpc/cpp/classgrpc_1_1_client_async_reader_writer.html" rel="nofollow noreferrer">ClientAsyncReaderWriter</a>:</strong></p>
  
  <ul>
  <li>First use asyncXXX(), this API use CreateCall() and register Write() (<code>ext_ref == 2</code>).</li>
  <li>Then it uses AsyncNext() to get tag...which must use a write or read operator. </li>
  <li>So <code>ext_ref &gt; 1</code> forever, unless got_event you don't handle.</li>
  </ul>
  
  <p>I'm calling it like this:</p>
  
  <pre><code>struct Notice
  {
      std::unique_ptr&lt;
          grpc::ClientAsyncReaderWriter&lt;ObserveNoticRequest, EventNotice&gt;
      &gt;                          _rw;
      ClientContext              _context;
      EventNotice                _rsp;
  }
  </code></pre>
  
  <h2>Register Thread</h2>
  
  <pre><code>CompletionQueue *cq = new CompletionQueue;
  Notice *notice = new Notice;
  notice-&gt;rw = stub-&gt;AsyncobserverNotice(&amp;context, cq, notice); 
  
  // here context.call_.ext_ref is 2
  </code></pre>
  
  <h1>Get CompletionQueue Event Thread</h1>
  
  <pre><code>void *tag = NULL;
  bool ok = false;
  CompletionQueue::NextStatus got = CompletionQueue::NextStatus::TIMEOUT;
  gpr_timespec deadline;
  deadline.clock_type = GPR_TIMESPAN;
  deadline.tv_sec = 0;
  deadline.tv_nsec = 10000000;
  
  got = cq-&gt;AsyncNext&lt;gpr_timespec&gt;(&amp;tag, &amp;ok, deadline);
  
  if (GOT_EVENT == got) {
      if (tag != NULL) {
          Notice *notice = (Notice *)tag;
          notice-&gt;_rw-&gt;Read(&amp;_rsp, notice);
  
          // here context.call_.ext_ref is 2.
          // now I want to stop this CompletionQueue. 
  
          delete notice;
  
          // use ~ClientContext(), ext_ref change to 1
          // but only ext_ref == 0, call_ be deleted
      }
  }
  </code></pre>