2 * Copyright 2015 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <type_traits>
21 #include <folly/wangle/channel/Pipeline.h>
23 namespace folly { namespace wangle {
26 * StaticPipeline allows you to create a Pipeline with minimal allocations.
27 * Specify your handlers after the input/output types of your Pipeline in order
28 * from front to back, and construct with either H&&, H*, or std::shared_ptr<H>
29 * for each handler. The pipeline will be finalized for you at the end of
30 * construction. For example:
32 * StringToStringHandler stringHandler1;
33 * auto stringHandler2 = std::make_shared<StringToStringHandler>();
35 * StaticPipeline<int, std::string,
37 * StringToStringHandler,
38 * StringToStringHandler>(
39 * IntToStringHandler(), // H&&
40 * &stringHandler1, // H*
41 * stringHandler2) // std::shared_ptr<H>
44 * You can then use pipeline just like any Pipeline. See Pipeline.h.
46 template <class R, class W, class... Handlers>
49 template <class R, class W>
50 class StaticPipeline<R, W> : public Pipeline<R, W> {
52 explicit StaticPipeline(bool) : Pipeline<R, W>(true) {}
55 template <class Handler>
56 class BaseWithOptional {
58 folly::Optional<Handler> handler_;
61 template <class Handler>
62 class BaseWithoutOptional {
65 template <class R, class W, class Handler, class... Handlers>
66 class StaticPipeline<R, W, Handler, Handlers...>
67 : public StaticPipeline<R, W, Handlers...>
68 , public std::conditional<std::is_abstract<Handler>::value,
69 BaseWithoutOptional<Handler>,
70 BaseWithOptional<Handler>>::type {
72 template <class... HandlerArgs>
73 explicit StaticPipeline(HandlerArgs&&... handlers)
74 : StaticPipeline(true, std::forward<HandlerArgs>(handlers)...) {
80 Pipeline<R, W>::detachHandlers();
85 template <class HandlerArg, class... HandlerArgs>
89 HandlerArgs&&... handlers)
90 : StaticPipeline<R, W, Handlers...>(
92 std::forward<HandlerArgs>(handlers)...) {
94 setHandler(std::forward<HandlerArg>(handler));
96 ctx_.initialize(this, handlerPtr_);
97 Pipeline<R, W>::addContextFront(&ctx_);
99 Pipeline<R, W>::finalize();
104 template <class HandlerArg>
105 typename std::enable_if<std::is_same<
106 typename std::remove_reference<HandlerArg>::type,
109 setHandler(HandlerArg&& arg) {
110 BaseWithOptional<Handler>::handler_.emplace(std::forward<HandlerArg>(arg));
111 handlerPtr_ = std::shared_ptr<Handler>(&(*BaseWithOptional<Handler>::handler_), [](Handler*){});
114 template <class HandlerArg>
115 typename std::enable_if<std::is_same<
116 typename std::decay<HandlerArg>::type,
117 std::shared_ptr<Handler>
119 setHandler(HandlerArg&& arg) {
120 handlerPtr_ = std::forward<HandlerArg>(arg);
123 template <class HandlerArg>
124 typename std::enable_if<std::is_same<
125 typename std::decay<HandlerArg>::type,
128 setHandler(HandlerArg&& arg) {
129 handlerPtr_ = std::shared_ptr<Handler>(arg, [](Handler*){});
133 std::shared_ptr<Handler> handlerPtr_;
134 typename ContextType<Handler, Pipeline<R, W>>::type ctx_;