Adopt the static factory pattern (#10)

* Switch sync streams from "struct internal" to static factory in namespace internal

* Reduce diff size

* fix friends

* Use static factory pattern for async unary calls

* Use static factories for async streams

* clang-format
pull/13107/head
Vijay Pai 7 years ago committed by GitHub
parent 06e174a088
commit 7a648854e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 147
      include/grpc++/impl/codegen/async_stream.h
  2. 43
      include/grpc++/impl/codegen/async_unary_call.h
  3. 24
      include/grpc++/impl/codegen/channel_interface.h
  4. 70
      include/grpc++/impl/codegen/sync_stream.h
  5. 24
      src/compiler/cpp_generator.cc
  6. 4
      src/cpp/client/generic_stub.cc

@ -159,33 +159,37 @@ class ClientAsyncReaderInterface
: public internal::ClientAsyncStreamingInterface,
public internal::AsyncReaderInterface<R> {};
namespace internal {
template <class R>
class ClientAsyncReaderFactory {
public:
/// Create a stream object.
/// Write the first request out if \a start is set.
/// \a tag will be notified on \a cq when the call has been started and
/// \a request has been written out. If \a start is not set, \a tag must be
/// nullptr and the actual call must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call.
template <class W>
static ClientAsyncReader<R>* Create(ChannelInterface* channel,
CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, const W& request,
bool start, void* tag) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncReader<R>)))
ClientAsyncReader<R>(call, context, request, start, tag);
}
};
} // namespace internal
/// Async client-side API for doing server-streaming RPCs,
/// where the incoming message stream coming from the server has
/// messages of type \a R.
template <class R>
class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
public:
struct internal {
/// Create a stream object.
/// Write the first request out if \a start is set.
/// \a tag will be notified on \a cq when the call has been started and
/// \a request has been written out. If \a start is not set, \a tag must be
/// nullptr and the actual call must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call.
template <class W>
static ClientAsyncReader* Create(ChannelInterface* channel,
CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, const W& request,
bool start, void* tag) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncReader)))
ClientAsyncReader(call, context, request, start, tag);
}
};
// always allocated against a call arena, no memory free required
static void operator delete(void* ptr, std::size_t size) {
assert(size == sizeof(ClientAsyncReader));
@ -240,6 +244,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
}
private:
friend class internal::ClientAsyncReaderFactory<R>;
template <class W>
ClientAsyncReader(::grpc::internal::Call call, ClientContext* context,
const W& request, bool start, void* tag)
@ -291,37 +296,41 @@ class ClientAsyncWriterInterface
virtual void WritesDone(void* tag) = 0;
};
namespace internal {
template <class W>
class ClientAsyncWriterFactory {
public:
/// Create a stream object.
/// Start the RPC if \a start is set
/// \a tag will be notified on \a cq when the call has been started (i.e.
/// intitial metadata sent) and \a request has been written out.
/// If \a start is not set, \a tag must be nullptr and the actual call
/// must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call.
/// \a response will be filled in with the single expected response
/// message from the server upon a successful call to the \a Finish
/// method of this instance.
template <class R>
static ClientAsyncWriter<W>* Create(ChannelInterface* channel,
CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, R* response,
bool start, void* tag) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncWriter<W>)))
ClientAsyncWriter<W>(call, context, response, start, tag);
}
};
} // namespace internal
/// Async API on the client side for doing client-streaming RPCs,
/// where the outgoing message stream going to the server contains
/// messages of type \a W.
template <class W>
class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
public:
struct internal {
/// Create a stream object.
/// Start the RPC if \a start is set
/// \a tag will be notified on \a cq when the call has been started (i.e.
/// intitial metadata sent) and \a request has been written out.
/// If \a start is not set, \a tag must be nullptr and the actual call
/// must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call.
/// \a response will be filled in with the single expected response
/// message from the server upon a successful call to the \a Finish
/// method of this instance.
template <class R>
static ClientAsyncWriter* Create(ChannelInterface* channel,
CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, R* response,
bool start, void* tag) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncWriter)))
ClientAsyncWriter(call, context, response, start, tag);
}
};
// always allocated against a call arena, no memory free required
static void operator delete(void* ptr, std::size_t size) {
assert(size == sizeof(ClientAsyncWriter));
@ -394,6 +403,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
}
private:
friend class internal::ClientAsyncWriterFactory<W>;
template <class R>
ClientAsyncWriter(::grpc::internal::Call call, ClientContext* context,
R* response, bool start, void* tag)
@ -449,6 +459,30 @@ class ClientAsyncReaderWriterInterface
virtual void WritesDone(void* tag) = 0;
};
namespace internal {
template <class W, class R>
class ClientAsyncReaderWriterFactory {
public:
/// Create a stream object.
/// Start the RPC request if \a start is set.
/// \a tag will be notified on \a cq when the call has been started (i.e.
/// intitial metadata sent). If \a start is not set, \a tag must be
/// nullptr and the actual call must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call.
static ClientAsyncReaderWriter<W, R>* Create(
ChannelInterface* channel, CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method, ClientContext* context,
bool start, void* tag) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncReaderWriter<W, R>)))
ClientAsyncReaderWriter<W, R>(call, context, start, tag);
}
};
} // namespace internal
/// Async client-side interface for bi-directional streaming,
/// where the outgoing message stream going to the server
/// has messages of type \a W, and the incoming message stream coming
@ -457,26 +491,6 @@ template <class W, class R>
class ClientAsyncReaderWriter final
: public ClientAsyncReaderWriterInterface<W, R> {
public:
struct internal {
/// Create a stream object.
/// Start the RPC request if \a start is set.
/// \a tag will be notified on \a cq when the call has been started (i.e.
/// intitial metadata sent). If \a start is not set, \a tag must be
/// nullptr and the actual call must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call.
static ClientAsyncReaderWriter* Create(
ChannelInterface* channel, CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method, ClientContext* context,
bool start, void* tag) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncReaderWriter)))
ClientAsyncReaderWriter(call, context, start, tag);
}
};
// always allocated against a call arena, no memory free required
static void operator delete(void* ptr, std::size_t size) {
assert(size == sizeof(ClientAsyncReaderWriter));
@ -556,6 +570,7 @@ class ClientAsyncReaderWriter final
}
private:
friend class internal::ClientAsyncReaderWriterFactory<W, R>;
ClientAsyncReaderWriter(::grpc::internal::Call call, ClientContext* context,
bool start, void* tag)
: context_(context), call_(call), started_(start) {

@ -69,31 +69,35 @@ class ClientAsyncResponseReaderInterface {
virtual void Finish(R* msg, Status* status, void* tag) = 0;
};
namespace internal {
template <class R>
class ClientAsyncResponseReaderFactory {
public:
/// Start a call and write the request out if \a start is set.
/// \a tag will be notified on \a cq when the call has been started (i.e.
/// intitial metadata sent) and \a request has been written out.
/// If \a start is not set, the actual call must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call.
template <class W>
static ClientAsyncResponseReader<R>* Create(
ChannelInterface* channel, CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method, ClientContext* context,
const W& request, bool start) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncResponseReader<R>)))
ClientAsyncResponseReader<R>(call, context, request, start);
}
};
} // namespace internal
/// Async API for client-side unary RPCs, where the message response
/// received from the server is of type \a R.
template <class R>
class ClientAsyncResponseReader final
: public ClientAsyncResponseReaderInterface<R> {
public:
struct internal {
/// Start a call and write the request out if \a start is set.
/// \a tag will be notified on \a cq when the call has been started (i.e.
/// intitial metadata sent) and \a request has been written out.
/// If \a start is not set, the actual call must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call.
template <class W>
static ClientAsyncResponseReader* Create(
ChannelInterface* channel, CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method, ClientContext* context,
const W& request, bool start) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncResponseReader)))
ClientAsyncResponseReader(call, context, request, start);
}
};
// always allocated against a call arena, no memory free required
static void operator delete(void* ptr, std::size_t size) {
assert(size == sizeof(ClientAsyncResponseReader));
@ -138,6 +142,7 @@ class ClientAsyncResponseReader final
}
private:
friend class internal::ClientAsyncResponseReaderFactory<R>;
ClientContext* const context_;
::grpc::internal::Call call_;
bool started_;

@ -34,14 +34,6 @@ template <class W>
class ClientWriter;
template <class W, class R>
class ClientReaderWriter;
template <class R>
class ClientAsyncReader;
template <class W>
class ClientAsyncWriter;
template <class W, class R>
class ClientAsyncReaderWriter;
template <class R>
class ClientAsyncResponseReader;
namespace internal {
class Call;
@ -49,6 +41,14 @@ class CallOpSetInterface;
class RpcMethod;
template <class InputMessage, class OutputMessage>
class BlockingUnaryCallImpl;
template <class R>
class ClientAsyncReaderFactory;
template <class W>
class ClientAsyncWriterFactory;
template <class W, class R>
class ClientAsyncReaderWriterFactory;
template <class R>
class ClientAsyncResponseReaderFactory;
} // namespace internal
/// Codegen interface for \a grpc::Channel.
@ -94,13 +94,13 @@ class ChannelInterface {
template <class W, class R>
friend class ::grpc::ClientReaderWriter;
template <class R>
friend class ::grpc::ClientAsyncReader;
friend class ::grpc::internal::ClientAsyncReaderFactory;
template <class W>
friend class ::grpc::ClientAsyncWriter;
friend class ::grpc::internal::ClientAsyncWriterFactory;
template <class W, class R>
friend class ::grpc::ClientAsyncReaderWriter;
friend class ::grpc::internal::ClientAsyncReaderWriterFactory;
template <class R>
friend class ::grpc::ClientAsyncResponseReader;
friend class ::grpc::internal::ClientAsyncResponseReaderFactory;
template <class InputMessage, class OutputMessage>
friend class ::grpc::internal::BlockingUnaryCallImpl;
friend class ::grpc::internal::RpcMethod;

@ -156,21 +156,25 @@ class ClientReaderInterface : public internal::ClientStreamingInterface,
virtual void WaitForInitialMetadata() = 0;
};
namespace internal {
template <class R>
class ClientReaderFactory {
public:
template <class W>
static ClientReader<R>* Create(ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, const W& request) {
return new ClientReader<R>(channel, method, context, request);
}
};
} // namespace internal
/// Synchronous (blocking) client-side API for doing server-streaming RPCs,
/// where the stream of messages coming from the server has messages
/// of type \a R.
template <class R>
class ClientReader final : public ClientReaderInterface<R> {
public:
struct internal {
template <class W>
static ClientReader* Create(ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, const W& request) {
return new ClientReader(channel, method, context, request);
}
};
/// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
/// semantics.
///
@ -225,6 +229,7 @@ class ClientReader final : public ClientReaderInterface<R> {
}
private:
friend class internal::ClientReaderFactory<R>;
ClientContext* context_;
CompletionQueue cq_;
::grpc::internal::Call call_;
@ -269,21 +274,25 @@ class ClientWriterInterface : public internal::ClientStreamingInterface,
virtual bool WritesDone() = 0;
};
namespace internal {
template <class W>
class ClientWriterFactory {
public:
template <class R>
static ClientWriter<W>* Create(::grpc::ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, R* response) {
return new ClientWriter<W>(channel, method, context, response);
}
};
} // namespace internal
/// Synchronous (blocking) client-side API for doing client-streaming RPCs,
/// where the outgoing message stream coming from the client has messages of
/// type \a W.
template <class W>
class ClientWriter : public ClientWriterInterface<W> {
public:
struct internal {
template <class R>
static ClientWriter* Create(::grpc::ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, R* response) {
return new ClientWriter(channel, method, context, response);
}
};
/// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
/// semantics.
///
@ -355,12 +364,13 @@ class ClientWriter : public ClientWriterInterface<W> {
}
private:
friend class internal::ClientWriterFactory<W>;
/// Block to create a stream (i.e. send request headers and other initial
/// metadata to the server). Note that \a context will be used to fill
/// in custom initial metadata. \a response will be filled in with the
/// single expected response message from the server upon a successful
/// call to the \a Finish method of this instance.
template <class R>
ClientWriter(ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
@ -415,6 +425,18 @@ class ClientReaderWriterInterface : public internal::ClientStreamingInterface,
virtual bool WritesDone() = 0;
};
namespace internal {
template <class W, class R>
class ClientReaderWriterFactory {
public:
static ClientReaderWriter<W, R>* Create(
::grpc::ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method, ClientContext* context) {
return new ClientReaderWriter<W, R>(channel, method, context);
}
};
} // namespace internal
/// Synchronous (blocking) client-side API for bi-directional streaming RPCs,
/// where the outgoing message stream coming from the client has messages of
/// type \a W, and the incoming messages stream coming from the server has
@ -422,14 +444,6 @@ class ClientReaderWriterInterface : public internal::ClientStreamingInterface,
template <class W, class R>
class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
public:
struct internal {
static ClientReaderWriter* Create(::grpc::ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context) {
return new ClientReaderWriter(channel, method, context);
}
};
/// Block waiting to read initial metadata from the server.
/// This call is optional, but if it is used, it cannot be used concurrently
/// with or after the \a Finish method.
@ -523,6 +537,8 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
}
private:
friend class internal::ClientReaderWriterFactory<W, R>;
ClientContext* context_;
CompletionQueue cq_;
::grpc::internal::Call call_;

@ -1203,8 +1203,8 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
printer->Print(
*vars,
" return "
"::grpc::ClientAsyncResponseReader< $Response$>::internal::Create("
"channel_.get(), cq, "
"::grpc::internal::ClientAsyncResponseReaderFactory< $Response$>"
"::Create(channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, request, $AsyncStart$);\n"
"}\n\n");
@ -1216,7 +1216,7 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"::grpc::ClientContext* context, $Response$* response) {\n");
printer->Print(
*vars,
" return ::grpc::ClientWriter< $Request$>::internal::Create("
" return ::grpc::internal::ClientWriterFactory< $Request$>::Create("
"channel_.get(), "
"rpcmethod_$Method$_, "
"context, response);\n"
@ -1233,8 +1233,8 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Print(
*vars,
" return ::grpc::ClientAsyncWriter< $Request$>::internal::Create("
"channel_.get(), cq, "
" return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
"::Create(channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, response, $AsyncStart$$AsyncCreateArgs$);\n"
"}\n\n");
@ -1247,7 +1247,7 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"::grpc::ClientContext* context, const $Request$& request) {\n");
printer->Print(
*vars,
" return ::grpc::ClientReader< $Response$>::internal::Create("
" return ::grpc::internal::ClientReaderFactory< $Response$>::Create("
"channel_.get(), "
"rpcmethod_$Method$_, "
"context, request);\n"
@ -1265,8 +1265,8 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Print(
*vars,
" return ::grpc::ClientAsyncReader< $Response$>::internal::Create("
"channel_.get(), cq, "
" return ::grpc::internal::ClientAsyncReaderFactory< $Response$>"
"::Create(channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, request, $AsyncStart$$AsyncCreateArgs$);\n"
"}\n\n");
@ -1277,8 +1277,8 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
"$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
printer->Print(*vars,
" return ::grpc::ClientReaderWriter< "
"$Request$, $Response$>::internal::Create("
" return ::grpc::internal::ClientReaderWriterFactory< "
"$Request$, $Response$>::Create("
"channel_.get(), "
"rpcmethod_$Method$_, "
"context);\n"
@ -1295,8 +1295,8 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Print(*vars,
" return "
"::grpc::ClientAsyncReaderWriter< $Request$, "
"$Response$>::internal::Create("
"::grpc::internal::ClientAsyncReaderWriterFactory< "
"$Request$, $Response$>::Create("
"channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, $AsyncStart$$AsyncCreateArgs$);\n"

@ -27,7 +27,7 @@ std::unique_ptr<GenericClientAsyncReaderWriter> CallInternal(
ChannelInterface* channel, ClientContext* context,
const grpc::string& method, CompletionQueue* cq, bool start, void* tag) {
return std::unique_ptr<GenericClientAsyncReaderWriter>(
GenericClientAsyncReaderWriter::internal::Create(
internal::ClientAsyncReaderWriterFactory<ByteBuffer, ByteBuffer>::Create(
channel, cq, internal::RpcMethod(method.c_str(),
internal::RpcMethod::BIDI_STREAMING),
context, start, tag));
@ -53,7 +53,7 @@ std::unique_ptr<GenericClientAsyncResponseReader> GenericStub::PrepareUnaryCall(
ClientContext* context, const grpc::string& method,
const ByteBuffer& request, CompletionQueue* cq) {
return std::unique_ptr<GenericClientAsyncResponseReader>(
GenericClientAsyncResponseReader::internal::Create(
internal::ClientAsyncResponseReaderFactory<ByteBuffer>::Create(
channel_.get(), cq,
internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC),
context, request, false));

Loading…
Cancel
Save