Hello Nathan,

Am Montag, 15. Oktober 2018 17:54:48 UTC+2 schrieb Nathan Prat:
>
> How can you use CRTP? I tried it this way, but after `cq_->Next` you can't 
> static_cast to a templated class. Or am I missing something?
>

I have a mixture now of virtual inheritance and CRTP.

Basically, one super simple call root class:

// First a macro I use later
#define GRPC_NATIVE_NAME_REQUEST( name )              \
void native_name_request() {                                           \
m_service->Request ## name ## (&m_ctx, &m_request, &m_responder, m_cq, 
m_cq, this);    \
}


class RpcCallBase {

    public:
        RpcCallBase() {};
        virtual ~RpcCallBase() {};

        virtual void proceed() noexcept {
              MOOSE_ASSERT_MSG(true, "RPC implementation does not overload 
proceed()");
        };
};

This is what I use to cast the void ptr to in order to get it to RTTI the 
right type. Then, on top of this, the actual CRTP base. Like this:

// First a macro I use later
#define GRPC_NATIVE_NAME_REQUEST( name )              \
void native_name_request() {                                           \
m_service->Request ## name ## (&m_ctx, &m_request, &m_responder, m_cq, 
m_cq, this);    \
}


template< class DerivedType, class RequestType, class ResponseType >
class MyServiceCall : public RpcCallBase {

    public:

        typedef MyServiceCall<DerivedType, RequestType, ResponseType> 
base_type;

MyServiceCall() {
             // constructor with service specific stuff such as parent 
object and so on
             proceed();  like in the example
        }

        void proceed() noexcept override {
             // Much like the example, except:
             if (m_status == CREATE) {
                   m_status = PROCESS;
                   static_cast<DerivedType *>(this)->native_name_request();

             // this is what the macro injects in order to fake the right 
type in here. See below.
             } else if (m_status == PROCESS) {
                    // new object of CRTP derived type
                    new base_type(m_service, m_cq, m_parent);
                   
                    // CRTP to the actual work, overloaded by derived class
                    grpc::Status retstat = static_cast<DerivedType 
*>(this)->work();

              }
    // rest of the stuff pretty much like the example except template types
}

and then, each call can be implemented nicely:

class FooMethodCall : public MyServiceCall<FooMethodCall, FooMethodRequest, 
FooMethodResponse> {

    public:
        GRPC_NATIVE_NAME_REQUEST( FooMethod )   // I know, not perfect but 
it does the trick

        FooMethodCall(MyService::AsyncService *n_service, 
ServerCompletionQueue *n_cq, MyServiceImpl *n_parent)
              : base_type(n_service, n_cq, n_parent) {
        }

        grpc::Status work() {
                      
                    // do the actual work and return a status object
        }     
}


Finally, in the async loop it looks like this:

void MyServiceImpl::HandleRpcs() {

    // Spawn a new CallData instance to serve new clients.
    // The q takes ownership
    new FooMethodCall(&m_service_instance, m_cq.get(), this);
    new BarMethodCall(&m_service_instance, m_cq.get(), this);

    void* tag;  // uniquely identifies a request.

    bool ok;
    while (true) {
        
         if (!m_cq->Next(&tag, &ok)) {
               BOOST_LOG_SEV(logger(), normal) << "service shutting down";
               break;
         }

         RpcCallBase *call = static_cast<RpcCallBase *>(tag);

         if (!ok) {
               // This seems to be the case while the q is draining of 
events 
               // during shutdown I'm gonna delete them
               delete call;
               continue;
          }

          // hand over to the call object to do the rest
          call->proceed();
     }
}

And it works. This way I don't need any further type guessing or casting 
beyond the RpcCallBase 

HTH,
Stephan

-- 
You received this message because you are subscribed to the Google Groups 
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/grpc-io.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/grpc-io/922f4158-87db-4d2e-a0eb-3266aee45137%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to