def run_on_client(requests,
                      set_input_stream_done,
                      set_output_stream_done,
                      &blk)
      @enq_th = Thread.new do
        write_loop(requests, set_output_stream_done: set_output_stream_done)
      end
      read_loop(set_input_stream_done, &blk)
    end
def run_on_client(requests,
                      set_input_stream_done,
                      set_output_stream_done,
                      &blk)
      @enq_th = Thread.new do
        write_loop(requests, set_output_stream_done: set_output_stream_done)
      end
      read_loop(set_input_stream_done, &blk)
    end
Creates a BidiCall.

 BidiCall should only be created after a call is accepted.  That means
 different things on a client and a server.  On the client, the call is
 accepted after call.invoke. On the server, this is after call.accept.

 #initialize cannot determine if the call is accepted or not; so if a
 call that's not accepted is used here, the error won't be visible until
 the BidiCall#run is called.

 deadline is the absolute deadline for the call.

 @param call [Call] the call used by the ActiveCall
 @param marshal [Function] f(obj)->string that marshal requests
 @param unmarshal [Function] f(string)->obj that unmarshals responses
 @param metadata_received [true|false] indicates if metadata has already
     been received. Should always be true for server calls
 Begins orchestration of the Bidi stream for a client sending requests.

 The method either returns an Enumerator of the responses, or accepts a
 block that can be invoked with each response.

 @param requests the Enumerable of requests to send
 @param set_input_stream_done [Proc] called back when we're done
   reading the input stream
 @param set_output_stream_done [Proc] called back when we're done
   sending data on the output stream
 @return an Enumerator of requests to yield