From: James Sedgwick Date: Thu, 30 Apr 2015 00:56:02 +0000 (-0700) Subject: moar CRTP to minimize copypasta for inbound/outbound handlers X-Git-Tag: v0.38.0~35 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=dded90960871719f2ab5e18ce6c7fa41ec2d545a;p=folly.git moar CRTP to minimize copypasta for inbound/outbound handlers Summary: I think this is the best I can do to minimize whjat must be copied for InboundHandler, InboundHandlerContext, InboundContextImpl, outbound equivalents, etc Test Plan: unit Reviewed By: davejwatson@fb.com Subscribers: fugalh, folly-diffs@, jsedgwick, yfeldblum, chalfant FB internal diff: D2025612 Tasks: 6836580 Signature: t1:2025612:1430346200:bc06162711bbc52b17574297a3569736f7973a7c --- diff --git a/folly/wangle/channel/Handler.h b/folly/wangle/channel/Handler.h index 05632e36..73d59a64 100644 --- a/folly/wangle/channel/Handler.h +++ b/folly/wangle/channel/Handler.h @@ -43,7 +43,7 @@ class HandlerBase { } private: - friend detail::HandlerContextBase; + friend PipelineContext; uint64_t attachCount_{0}; Context* ctx_{nullptr}; }; diff --git a/folly/wangle/channel/HandlerContext.h b/folly/wangle/channel/HandlerContext.h index 77762d8c..4bd79f5f 100644 --- a/folly/wangle/channel/HandlerContext.h +++ b/folly/wangle/channel/HandlerContext.h @@ -22,26 +22,8 @@ namespace folly { namespace wangle { -namespace detail { - -template -class HandlerContextBase { - protected: - template - void attachContext(H* handler, HandlerContext* ctx) { - if (++handler->attachCount_ == 1) { - handler->ctx_ = ctx; - } else { - handler->ctx_ = nullptr; - } - } -}; - -} // detail - template -class HandlerContext - : public detail::HandlerContextBase> { +class HandlerContext { public: virtual ~HandlerContext() {} @@ -83,6 +65,15 @@ class PipelineContext { virtual void attachTransport() = 0; virtual void detachTransport() = 0; + template + void attachContext(H* handler, HandlerContext* ctx) { + if (++handler->attachCount_ == 1) { + handler->ctx_ = ctx; + } else { + handler->ctx_ = nullptr; + } + } + void link(PipelineContext* other) { setNextIn(other); other->setNextOut(this); @@ -94,68 +85,62 @@ class PipelineContext { }; template -class InboundHandlerContext { +class InboundLink { public: - virtual ~InboundHandlerContext() {} + virtual ~InboundLink() {} virtual void read(In msg) = 0; virtual void readEOF() = 0; virtual void readException(exception_wrapper e) = 0; }; template -class OutboundHandlerContext { +class OutboundLink { public: - virtual ~OutboundHandlerContext() {} + virtual ~OutboundLink() {} virtual Future write(Out msg) = 0; virtual Future close() = 0; }; -template -class ContextImpl : public HandlerContext, - public InboundHandlerContext, - public OutboundHandlerContext, - public PipelineContext { +template +class ContextImplBase : public PipelineContext { public: - typedef typename H::rin Rin; - typedef typename H::rout Rout; - typedef typename H::win Win; - typedef typename H::wout Wout; + ~ContextImplBase() {} - explicit ContextImpl(P* pipeline, std::shared_ptr handler) { - initialize(pipeline, std::move(handler)); + H* getHandler() { + return handler_.get(); } - // For StaticPipeline - ContextImpl() {} - - ~ContextImpl() {} - void initialize(P* pipeline, std::shared_ptr handler) { pipeline_ = pipeline; handler_ = std::move(handler); } - H* getHandler() { - return handler_.get(); - } - // PipelineContext overrides void attachPipeline() override { if (!attached_) { - this->attachContext(handler_.get(), this); - handler_->attachPipeline(this); + this->attachContext(handler_.get(), impl_); + handler_->attachPipeline(impl_); attached_ = true; } } void detachPipeline() override { - handler_->detachPipeline(this); + handler_->detachPipeline(impl_); attached_ = false; } + void attachTransport() override { + DestructorGuard dg(pipeline_); + handler_->attachTransport(impl_); + } + + void detachTransport() override { + DestructorGuard dg(pipeline_); + handler_->detachTransport(impl_); + } + void setNextIn(PipelineContext* ctx) override { - auto nextIn = dynamic_cast*>(ctx); + auto nextIn = dynamic_cast*>(ctx); if (nextIn) { nextIn_ = nextIn; } else { @@ -164,7 +149,7 @@ class ContextImpl : public HandlerContext*>(ctx); + auto nextOut = dynamic_cast*>(ctx); if (nextOut) { nextOut_ = nextOut; } else { @@ -172,48 +157,74 @@ class ContextImpl : public HandlerContext(pipeline_)); - handler_->attachTransport(this); + protected: + Context* impl_; + P* pipeline_; + std::shared_ptr handler_; + InboundLink* nextIn_{nullptr}; + OutboundLink* nextOut_{nullptr}; + + private: + bool attached_{false}; + using DestructorGuard = typename P::DestructorGuard; +}; + +template +class ContextImpl : public HandlerContext, + public InboundLink, + public OutboundLink, + public ContextImplBase> { + public: + typedef typename H::rin Rin; + typedef typename H::rout Rout; + typedef typename H::win Win; + typedef typename H::wout Wout; + + explicit ContextImpl(P* pipeline, std::shared_ptr handler) { + this->impl_ = this; + this->initialize(pipeline, std::move(handler)); } - void detachTransport() override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - handler_->detachTransport(this); + // For StaticPipeline + ContextImpl() { + this->impl_ = this; } + ~ContextImpl() {} + // HandlerContext overrides void fireRead(Rout msg) override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - if (nextIn_) { - nextIn_->read(std::forward(msg)); + DestructorGuard dg(this->pipeline_); + if (this->nextIn_) { + this->nextIn_->read(std::forward(msg)); } else { LOG(WARNING) << "read reached end of pipeline"; } } void fireReadEOF() override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - if (nextIn_) { - nextIn_->readEOF(); + DestructorGuard dg(this->pipeline_); + if (this->nextIn_) { + this->nextIn_->readEOF(); } else { LOG(WARNING) << "readEOF reached end of pipeline"; } } void fireReadException(exception_wrapper e) override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - if (nextIn_) { - nextIn_->readException(std::move(e)); + DestructorGuard dg(this->pipeline_); + if (this->nextIn_) { + this->nextIn_->readException(std::move(e)); } else { LOG(WARNING) << "readException reached end of pipeline"; } } Future fireWrite(Wout msg) override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - if (nextOut_) { - return nextOut_->write(std::forward(msg)); + DestructorGuard dg(this->pipeline_); + if (this->nextOut_) { + return this->nextOut_->write(std::forward(msg)); } else { LOG(WARNING) << "write reached end of pipeline"; return makeFuture(); @@ -221,9 +232,9 @@ class ContextImpl : public HandlerContext fireClose() override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - if (nextOut_) { - return nextOut_->close(); + DestructorGuard dg(this->pipeline_); + if (this->nextOut_) { + return this->nextOut_->close(); } else { LOG(WARNING) << "close reached end of pipeline"; return makeFuture(); @@ -231,60 +242,56 @@ class ContextImpl : public HandlerContext getTransport() override { - return pipeline_->getTransport(); + return this->pipeline_->getTransport(); } void setWriteFlags(WriteFlags flags) override { - pipeline_->setWriteFlags(flags); + this->pipeline_->setWriteFlags(flags); } WriteFlags getWriteFlags() override { - return pipeline_->getWriteFlags(); + return this->pipeline_->getWriteFlags(); } void setReadBufferSettings( uint64_t minAvailable, uint64_t allocationSize) override { - pipeline_->setReadBufferSettings(minAvailable, allocationSize); + this->pipeline_->setReadBufferSettings(minAvailable, allocationSize); } std::pair getReadBufferSettings() override { - return pipeline_->getReadBufferSettings(); + return this->pipeline_->getReadBufferSettings(); } - // InboundHandlerContext overrides + // InboundLink overrides void read(Rin msg) override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - handler_->read(this, std::forward(msg)); + DestructorGuard dg(this->pipeline_); + this->handler_->read(this, std::forward(msg)); } void readEOF() override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - handler_->readEOF(this); + DestructorGuard dg(this->pipeline_); + this->handler_->readEOF(this); } void readException(exception_wrapper e) override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - handler_->readException(this, std::move(e)); + DestructorGuard dg(this->pipeline_); + this->handler_->readException(this, std::move(e)); } - // OutboundHandlerContext overrides + // OutboundLink overrides Future write(Win msg) override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - return handler_->write(this, std::forward(msg)); + DestructorGuard dg(this->pipeline_); + return this->handler_->write(this, std::forward(msg)); } Future close() override { - typename P::DestructorGuard dg(static_cast(pipeline_)); - return handler_->close(this); + DestructorGuard dg(this->pipeline_); + return this->handler_->close(this); } private: - P* pipeline_; - std::shared_ptr handler_; - InboundHandlerContext* nextIn_{nullptr}; - OutboundHandlerContext* nextOut_{nullptr}; - bool attached_{false}; + using DestructorGuard = typename P::DestructorGuard; }; }} diff --git a/folly/wangle/channel/Pipeline.h b/folly/wangle/channel/Pipeline.h index 643ccdae..738a83f9 100644 --- a/folly/wangle/channel/Pipeline.h +++ b/folly/wangle/channel/Pipeline.h @@ -133,12 +133,12 @@ class Pipeline : public DelayedDestruction { ctxs_[i]->link(ctxs_[i+1].get()); } - back_ = dynamic_cast*>(ctxs_.back().get()); + back_ = dynamic_cast*>(ctxs_.back().get()); if (!back_) { throw std::invalid_argument("wrong type for last handler"); } - front_ = dynamic_cast*>(ctxs_.front().get()); + front_ = dynamic_cast*>(ctxs_.front().get()); if (!front_) { throw std::invalid_argument("wrong type for first handler"); } @@ -205,8 +205,8 @@ class Pipeline : public DelayedDestruction { std::pair readBufferSettings_{2048, 2048}; bool isStatic_{false}; - InboundHandlerContext* front_{nullptr}; - OutboundHandlerContext* back_{nullptr}; + InboundLink* front_{nullptr}; + OutboundLink* back_{nullptr}; std::vector> ctxs_; std::shared_ptr owner_; };