inbound/outbound handlers
[folly.git] / folly / wangle / channel / StaticPipeline.h
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <folly/wangle/channel/Pipeline.h>
20
21 namespace folly { namespace wangle {
22
23 /*
24  * StaticPipeline allows you to create a Pipeline with minimal allocations.
25  * Specify your handlers after the input/output types of your Pipeline in order
26  * from front to back, and construct with either H&&, H*, or std::shared_ptr<H>
27  * for each handler. The pipeline will be finalized for you at the end of
28  * construction. For example:
29  *
30  * StringToStringHandler stringHandler1;
31  * auto stringHandler2 = std::make_shared<StringToStringHandler>();
32  *
33  * StaticPipeline<int, std::string,
34  *   IntToStringHandler,
35  *   StringToStringHandler,
36  *   StringToStringHandler>(
37  *     IntToStringHandler(),  // H&&
38  *     &stringHandler1,       // H*
39  *     stringHandler2)        // std::shared_ptr<H>
40  * pipeline;
41  *
42  * You can then use pipeline just like any Pipeline. See Pipeline.h.
43  */
44 template <class R, class W, class... Handlers>
45 class StaticPipeline;
46
47 template <class R, class W>
48 class StaticPipeline<R, W> : public Pipeline<R, W> {
49  protected:
50   explicit StaticPipeline(bool) : Pipeline<R, W>(true) {}
51 };
52
53 template <class R, class W, class Handler, class... Handlers>
54 class StaticPipeline<R, W, Handler, Handlers...>
55     : public StaticPipeline<R, W, Handlers...> {
56  public:
57   template <class... HandlerArgs>
58   explicit StaticPipeline(HandlerArgs&&... handlers)
59     : StaticPipeline(true, std::forward<HandlerArgs>(handlers)...) {
60     isFirst_ = true;
61   }
62
63   ~StaticPipeline() {
64     if (isFirst_) {
65       Pipeline<R, W>::detachHandlers();
66     }
67   }
68
69  protected:
70   template <class HandlerArg, class... HandlerArgs>
71   StaticPipeline(
72       bool isFirst,
73       HandlerArg&& handler,
74       HandlerArgs&&... handlers)
75     : StaticPipeline<R, W, Handlers...>(
76           false,
77           std::forward<HandlerArgs>(handlers)...) {
78     isFirst_ = isFirst;
79     setHandler(std::forward<HandlerArg>(handler));
80     CHECK(handlerPtr_);
81     ctx_.initialize(this, handlerPtr_);
82     Pipeline<R, W>::addContextFront(&ctx_);
83     if (isFirst_) {
84       Pipeline<R, W>::finalize();
85     }
86   }
87
88  private:
89   template <class HandlerArg>
90   typename std::enable_if<std::is_same<
91     typename std::remove_reference<HandlerArg>::type,
92     Handler
93   >::value>::type
94   setHandler(HandlerArg&& arg) {
95     handler_.emplace(std::forward<HandlerArg>(arg));
96     handlerPtr_ = std::shared_ptr<Handler>(&(*handler_), [](Handler*){});
97   }
98
99   template <class HandlerArg>
100   typename std::enable_if<std::is_same<
101     typename std::decay<HandlerArg>::type,
102     std::shared_ptr<Handler>
103   >::value>::type
104   setHandler(HandlerArg&& arg) {
105     handlerPtr_ = std::forward<HandlerArg>(arg);
106   }
107
108   template <class HandlerArg>
109   typename std::enable_if<std::is_same<
110     typename std::decay<HandlerArg>::type,
111     Handler*
112   >::value>::type
113   setHandler(HandlerArg&& arg) {
114     handlerPtr_ = std::shared_ptr<Handler>(arg, [](Handler*){});
115   }
116
117   bool isFirst_;
118   folly::Optional<Handler> handler_;
119   std::shared_ptr<Handler> handlerPtr_;
120   typename ContextType<Handler, Pipeline<R, W>>::type ctx_;
121 };
122
123 }} // folly::wangle