Allocate using call arenas

pull/16610/head
Vijay Pai 6 years ago
parent d4afae9a56
commit 5474e92292
  1. 22
      include/grpcpp/impl/codegen/callback_common.h
  2. 19
      include/grpcpp/impl/codegen/client_callback.h
  3. 59
      src/cpp/common/callback_common.cc

@ -37,11 +37,14 @@ namespace internal {
class CallbackWithStatusTag {
public:
// TODO(vjpai): make impl and ops part of this structure to avoid allocation,
// ownership transfer, and delete
CallbackWithStatusTag(std::function<void(Status)> f, bool self_delete,
// always allocated against a call arena, no memory free required
static void operator delete(void* ptr, std::size_t size) {
assert(size == sizeof(CallbackWithStatusTag));
}
CallbackWithStatusTag(grpc_call* call, std::function<void(Status)> f,
CompletionQueueTag* ops);
~CallbackWithStatusTag() { delete ops_; }
~CallbackWithStatusTag() {}
void* tag() { return static_cast<void*>(impl_); }
Status* status_ptr() { return status_; }
CompletionQueueTag* ops() { return ops_; }
@ -57,11 +60,14 @@ class CallbackWithStatusTag {
class CallbackWithSuccessTag {
public:
// TODO(vjpai): make impl and ops part of this structure to avoid allocation,
// ownership transfer, and delete
CallbackWithSuccessTag(std::function<void(bool)> f, bool self_delete,
// always allocated against a call arena, no memory free required
static void operator delete(void* ptr, std::size_t size) {
assert(size == sizeof(CallbackWithSuccessTag));
}
CallbackWithSuccessTag(grpc_call* call, std::function<void(bool)> f,
CompletionQueueTag* ops);
~CallbackWithSuccessTag() { delete ops_; }
void* tag() { return static_cast<void*>(impl_); }
CompletionQueueTag* ops() { return ops_; }

@ -57,18 +57,21 @@ class CallbackUnaryCallImpl {
std::function<void(Status)> on_completion) {
CompletionQueue* cq = channel->CallbackCQ();
GPR_CODEGEN_ASSERT(cq != nullptr);
Call call(channel->CreateCall(method, context, cq));
using FullCallOpSet =
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>,
CallOpClientSendClose, CallOpClientRecvStatus>;
// TODO(vjpai): Allocate this as part of the tag's arena
auto* ops = new CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpRecvInitialMetadata,
CallOpRecvMessage<OutputMessage>,
CallOpClientSendClose, CallOpClientRecvStatus>;
auto* ops = new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(FullCallOpSet))) FullCallOpSet;
// TODO(vjpai): Move to using pre-allocated tags rather than new/self-delete
auto* tag = new CallbackWithStatusTag(on_completion, true, ops);
auto* tag = new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(CallbackWithStatusTag)))
CallbackWithStatusTag(call.call(), on_completion, ops);
// TODO(vjpai): Unify code with sync API as much as possible
Call call(channel->CreateCall(method, context, cq));
Status s = ops->SendMessage(*request);
if (!s.ok()) {
tag->force_run(s);

@ -30,9 +30,15 @@ namespace internal {
namespace {
class CallbackWithSuccessImpl : public grpc_core::CQCallbackInterface {
public:
CallbackWithSuccessImpl(CallbackWithSuccessTag* parent,
std::function<void(bool)> f, bool self_delete)
: parent_(parent), func_(std::move(f)), self_delete_(self_delete) {}
static void operator delete(void* ptr, std::size_t size) {
assert(size == sizeof(CallbackWithSuccessImpl));
}
CallbackWithSuccessImpl(grpc_call* call, CallbackWithSuccessTag* parent,
std::function<void(bool)> f)
: call_(call), parent_(parent), func_(std::move(f)) {
grpc_call_ref(call);
}
void Run(bool ok) override {
void* ignored = parent_->ops();
@ -40,27 +46,27 @@ class CallbackWithSuccessImpl : public grpc_core::CQCallbackInterface {
GPR_ASSERT(parent_->ops()->FinalizeResult(&ignored, &new_ok));
GPR_ASSERT(ignored == parent_->ops());
func_(ok);
if (self_delete_) {
delete parent_;
// Must use grpc_core::Delete since base is GRPC_ABSTRACT
grpc_core::Delete(this);
}
func_ = nullptr; // release the function
grpc_call_unref(call_);
}
private:
grpc_call* call_;
CallbackWithSuccessTag* parent_;
std::function<void(bool)> func_;
bool self_delete_;
};
class CallbackWithStatusImpl : public grpc_core::CQCallbackInterface {
public:
CallbackWithStatusImpl(CallbackWithStatusTag* parent,
std::function<void(Status)> f, bool self_delete)
: parent_(parent),
func_(std::move(f)),
status_(),
self_delete_(self_delete) {}
static void operator delete(void* ptr, std::size_t size) {
assert(size == sizeof(CallbackWithStatusImpl));
}
CallbackWithStatusImpl(grpc_call* call, CallbackWithStatusTag* parent,
std::function<void(Status)> f)
: call_(call), parent_(parent), func_(std::move(f)), status_() {
grpc_call_ref(call);
}
void Run(bool ok) override {
void* ignored = parent_->ops();
@ -69,36 +75,35 @@ class CallbackWithStatusImpl : public grpc_core::CQCallbackInterface {
GPR_ASSERT(ignored == parent_->ops());
func_(status_);
if (self_delete_) {
delete parent_;
// Must use grpc_core::Delete since base is GRPC_ABSTRACT
grpc_core::Delete(this);
}
func_ = nullptr; // release the function
grpc_call_unref(call_);
}
Status* status_ptr() { return &status_; }
private:
grpc_call* call_;
CallbackWithStatusTag* parent_;
std::function<void(Status)> func_;
Status status_;
bool self_delete_;
};
} // namespace
CallbackWithSuccessTag::CallbackWithSuccessTag(std::function<void(bool)> f,
bool self_delete,
CallbackWithSuccessTag::CallbackWithSuccessTag(grpc_call* call,
std::function<void(bool)> f,
CompletionQueueTag* ops)
: impl_(grpc_core::New<CallbackWithSuccessImpl>(this, f, self_delete)),
: impl_(new (grpc_call_arena_alloc(call, sizeof(CallbackWithSuccessImpl)))
CallbackWithSuccessImpl(call, this, std::move(f))),
ops_(ops) {}
void CallbackWithSuccessTag::force_run(bool ok) { impl_->Run(ok); }
CallbackWithStatusTag::CallbackWithStatusTag(std::function<void(Status)> f,
bool self_delete,
CallbackWithStatusTag::CallbackWithStatusTag(grpc_call* call,
std::function<void(Status)> f,
CompletionQueueTag* ops)
: ops_(ops) {
auto* impl = grpc_core::New<CallbackWithStatusImpl>(this, f, self_delete);
auto* impl = new (grpc_call_arena_alloc(call, sizeof(CallbackWithStatusImpl)))
CallbackWithStatusImpl(call, this, std::move(f));
impl_ = impl;
status_ = impl->status_ptr();
}

Loading…
Cancel
Save