Improvements to C++ filter API:

- Make sure all C-core parameters are passed into C++ methods.
- Add Destroy() methods for ChannelData and CallData.
- Use C++-style casts.
- Add 'extern "C"' to iomgr/closure.h, which is used in C++ filters.
pull/11648/head
Mark D. Roth 8 years ago
parent a410632b57
commit cc4ef5919f
  1. 8
      src/core/lib/iomgr/closure.h
  2. 54
      src/cpp/common/channel_filter.h
  3. 4
      test/cpp/common/channel_filter_test.cc

@ -26,6 +26,10 @@
#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error.h"
#include "src/core/lib/support/mpscq.h" #include "src/core/lib/support/mpscq.h"
#ifdef __cplusplus
extern "C" {
#endif
struct grpc_closure; struct grpc_closure;
typedef struct grpc_closure grpc_closure; typedef struct grpc_closure grpc_closure;
@ -197,4 +201,8 @@ void grpc_closure_list_sched(grpc_exec_ctx *exec_ctx,
grpc_closure_list_sched(exec_ctx, closure_list) grpc_closure_list_sched(exec_ctx, closure_list)
#endif #endif
#ifdef __cplusplus
}
#endif
#endif /* GRPC_CORE_LIB_IOMGR_CLOSURE_H */ #endif /* GRPC_CORE_LIB_IOMGR_CLOSURE_H */

@ -208,38 +208,45 @@ class TransportStreamOpBatch {
/// Represents channel data. /// Represents channel data.
class ChannelData { class ChannelData {
public: public:
ChannelData() {}
virtual ~ChannelData() {} virtual ~ChannelData() {}
/// Initializes the call data. // TODO(roth): Come up with a more C++-like API for the channel element.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx,
/// Initializes the channel data.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_channel_element_args *args) { grpc_channel_element_args *args) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
// TODO(roth): Find a way to avoid passing elem into these methods. // Called before destruction.
virtual void Destroy(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {}
virtual void StartTransportOp(grpc_exec_ctx *exec_ctx, virtual void StartTransportOp(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, TransportOp *op); grpc_channel_element *elem, TransportOp *op);
virtual void GetInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, virtual void GetInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
const grpc_channel_info *channel_info); const grpc_channel_info *channel_info);
protected:
ChannelData() {}
}; };
/// Represents call data. /// Represents call data.
class CallData { class CallData {
public: public:
CallData() {}
virtual ~CallData() {} virtual ~CallData() {}
// TODO(roth): Come up with a more C++-like API for the call element.
/// Initializes the call data. /// Initializes the call data.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, ChannelData *channel_data, virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_element_args *args) { const grpc_call_element_args *args) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
// TODO(roth): Find a way to avoid passing elem into these methods. // Called before destruction.
virtual void Destroy(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
grpc_closure *then_call_closure) {}
/// Starts a new stream operation. /// Starts a new stream operation.
virtual void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx, virtual void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx,
@ -253,9 +260,6 @@ class CallData {
/// Gets the peer name. /// Gets the peer name.
virtual char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem); virtual char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
protected:
CallData() {}
}; };
namespace internal { namespace internal {
@ -271,19 +275,24 @@ class ChannelFilter final {
static grpc_error *InitChannelElement(grpc_exec_ctx *exec_ctx, static grpc_error *InitChannelElement(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,
grpc_channel_element_args *args) { grpc_channel_element_args *args) {
// Construct the object in the already-allocated memory.
ChannelDataType *channel_data = new (elem->channel_data) ChannelDataType(); ChannelDataType *channel_data = new (elem->channel_data) ChannelDataType();
return channel_data->Init(exec_ctx, args); return channel_data->Init(exec_ctx, elem, args);
} }
static void DestroyChannelElement(grpc_exec_ctx *exec_ctx, static void DestroyChannelElement(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) { grpc_channel_element *elem) {
reinterpret_cast<ChannelDataType *>(elem->channel_data)->~ChannelDataType(); ChannelDataType *channel_data =
reinterpret_cast<ChannelDataType *>(elem->channel_data);
channel_data->Destroy(exec_ctx, elem);
channel_data->~ChannelDataType();
} }
static void StartTransportOp(grpc_exec_ctx *exec_ctx, static void StartTransportOp(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,
grpc_transport_op *op) { grpc_transport_op *op) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data; ChannelDataType *channel_data =
reinterpret_cast<ChannelDataType *>(elem->channel_data);
TransportOp op_wrapper(op); TransportOp op_wrapper(op);
channel_data->StartTransportOp(exec_ctx, elem, &op_wrapper); channel_data->StartTransportOp(exec_ctx, elem, &op_wrapper);
} }
@ -291,7 +300,8 @@ class ChannelFilter final {
static void GetChannelInfo(grpc_exec_ctx *exec_ctx, static void GetChannelInfo(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,
const grpc_channel_info *channel_info) { const grpc_channel_info *channel_info) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data; ChannelDataType *channel_data =
reinterpret_cast<ChannelDataType *>(elem->channel_data);
channel_data->GetInfo(exec_ctx, elem, channel_info); channel_data->GetInfo(exec_ctx, elem, channel_info);
} }
@ -300,24 +310,24 @@ class ChannelFilter final {
static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx, static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
const grpc_call_element_args *args) { const grpc_call_element_args *args) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data;
// Construct the object in the already-allocated memory. // Construct the object in the already-allocated memory.
CallDataType *call_data = new (elem->call_data) CallDataType(); CallDataType *call_data = new (elem->call_data) CallDataType();
return call_data->Init(exec_ctx, channel_data, args); return call_data->Init(exec_ctx, elem, args);
} }
static void DestroyCallElement(grpc_exec_ctx *exec_ctx, static void DestroyCallElement(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
grpc_closure *then_call_closure) { grpc_closure *then_call_closure) {
GPR_ASSERT(then_call_closure == NULL); CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
reinterpret_cast<CallDataType *>(elem->call_data)->~CallDataType(); call_data->Destroy(exec_ctx, elem, final_info, then_call_closure);
call_data->~CallDataType();
} }
static void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx, static void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_transport_stream_op_batch *op) { grpc_transport_stream_op_batch *op) {
CallDataType *call_data = (CallDataType *)elem->call_data; CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
TransportStreamOpBatch op_wrapper(op); TransportStreamOpBatch op_wrapper(op);
call_data->StartTransportStreamOpBatch(exec_ctx, elem, &op_wrapper); call_data->StartTransportStreamOpBatch(exec_ctx, elem, &op_wrapper);
} }
@ -325,12 +335,12 @@ class ChannelFilter final {
static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_polling_entity *pollent) { grpc_polling_entity *pollent) {
CallDataType *call_data = (CallDataType *)elem->call_data; CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
call_data->SetPollsetOrPollsetSet(exec_ctx, elem, pollent); call_data->SetPollsetOrPollsetSet(exec_ctx, elem, pollent);
} }
static char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { static char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
CallDataType *call_data = (CallDataType *)elem->call_data; CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
return call_data->GetPeer(exec_ctx, elem); return call_data->GetPeer(exec_ctx, elem);
} }
}; };

@ -28,7 +28,7 @@ class MyChannelData : public ChannelData {
public: public:
MyChannelData() {} MyChannelData() {}
grpc_error* Init(grpc_exec_ctx* exec_ctx, grpc_error* Init(grpc_exec_ctx* exec_ctx, grpc_channel_element* elem,
grpc_channel_element_args* args) override { grpc_channel_element_args* args) override {
(void)args->channel_args; // Make sure field is available. (void)args->channel_args; // Make sure field is available.
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
@ -39,7 +39,7 @@ class MyCallData : public CallData {
public: public:
MyCallData() {} MyCallData() {}
grpc_error* Init(grpc_exec_ctx* exec_ctx, ChannelData* channel_data, grpc_error* Init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
const grpc_call_element_args* args) override { const grpc_call_element_args* args) override {
(void)args->path; // Make sure field is available. (void)args->path; // Make sure field is available.
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;

Loading…
Cancel
Save