capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

function.h (10059B)


      1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
      2 // Licensed under the MIT License:
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 
     22 #pragma once
     23 
     24 #include "memory.h"
     25 
     26 KJ_BEGIN_HEADER
     27 
     28 namespace kj {
     29 
     30 template <typename Signature>
     31 class Function;
     32 // Function wrapper using virtual-based polymorphism.  Use this when template polymorphism is
     33 // not possible.  You can, for example, accept a Function as a parameter:
     34 //
     35 //     void setFilter(Function<bool(const Widget&)> filter);
     36 //
     37 // The caller of `setFilter()` may then pass any callable object as the parameter.  The callable
     38 // object does not have to have the exact signature specified, just one that is "compatible" --
     39 // i.e. the return type is covariant and the parameters are contravariant.
     40 //
     41 // Unlike `std::function`, `kj::Function`s are movable but not copyable, just like `kj::Own`.  This
     42 // is to avoid unexpected heap allocation or slow atomic reference counting.
     43 //
     44 // When a `Function` is constructed from an lvalue, it captures only a reference to the value.
     45 // When constructed from an rvalue, it invokes the value's move constructor.  So, for example:
     46 //
     47 //     struct AddN {
     48 //       int n;
     49 //       int operator(int i) { return i + n; }
     50 //     }
     51 //
     52 //     Function<int(int, int)> f1 = AddN{2};
     53 //     // f1 owns an instance of AddN.  It may safely be moved out
     54 //     // of the local scope.
     55 //
     56 //     AddN adder(2);
     57 //     Function<int(int, int)> f2 = adder;
     58 //     // f2 contains a reference to `adder`.  Thus, it becomes invalid
     59 //     // when `adder` goes out-of-scope.
     60 //
     61 //     AddN adder2(2);
     62 //     Function<int(int, int)> f3 = kj::mv(adder2);
     63 //     // f3 owns an insatnce of AddN moved from `adder2`.  f3 may safely
     64 //     // be moved out of the local scope.
     65 //
     66 // Additionally, a Function may be bound to a class method using KJ_BIND_METHOD(object, methodName).
     67 // For example:
     68 //
     69 //     class Printer {
     70 //     public:
     71 //       void print(int i);
     72 //       void print(kj::StringPtr s);
     73 //     };
     74 //
     75 //     Printer p;
     76 //
     77 //     Function<void(uint)> intPrinter = KJ_BIND_METHOD(p, print);
     78 //     // Will call Printer::print(int).
     79 //
     80 //     Function<void(const char*)> strPrinter = KJ_BIND_METHOD(p, print);
     81 //     // Will call Printer::print(kj::StringPtr).
     82 //
     83 // Notice how KJ_BIND_METHOD is able to figure out which overload to use depending on the kind of
     84 // Function it is binding to.
     85 
     86 template <typename Signature>
     87 class ConstFunction;
     88 // Like Function, but wraps a "const" (i.e. thread-safe) call.
     89 
     90 template <typename Signature>
     91 class FunctionParam;
     92 // Like Function, but used specifically as a call parameter type. Does not do any heap allocation.
     93 //
     94 // This type MUST NOT be used for anything other than a parameter type to a function or method.
     95 // This is because if FunctionParam binds to a temporary, it assumes that the temporary will
     96 // outlive the FunctionParam instance. This is true when FunctionParam is used as a parameter type,
     97 // but not if it is used as a local variable nor a class member variable.
     98 
     99 template <typename Return, typename... Params>
    100 class Function<Return(Params...)> {
    101 public:
    102   template <typename F>
    103   inline Function(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {}
    104   Function() = default;
    105 
    106   // Make sure people don't accidentally end up wrapping a reference when they meant to return
    107   // a function.
    108   KJ_DISALLOW_COPY(Function);
    109   Function(Function&) = delete;
    110   Function& operator=(Function&) = delete;
    111   template <typename T> Function(const Function<T>&) = delete;
    112   template <typename T> Function& operator=(const Function<T>&) = delete;
    113   template <typename T> Function(const ConstFunction<T>&) = delete;
    114   template <typename T> Function& operator=(const ConstFunction<T>&) = delete;
    115   Function(Function&&) = default;
    116   Function& operator=(Function&&) = default;
    117 
    118   inline Return operator()(Params... params) {
    119     return (*impl)(kj::fwd<Params>(params)...);
    120   }
    121 
    122   Function reference() {
    123     // Forms a new Function of the same type that delegates to this Function by reference.
    124     // Therefore, this Function must outlive the returned Function, but otherwise they behave
    125     // exactly the same.
    126 
    127     return *impl;
    128   }
    129 
    130 private:
    131   class Iface {
    132   public:
    133     virtual Return operator()(Params... params) = 0;
    134   };
    135 
    136   template <typename F>
    137   class Impl final: public Iface {
    138   public:
    139     explicit Impl(F&& f): f(kj::fwd<F>(f)) {}
    140 
    141     Return operator()(Params... params) override {
    142       return f(kj::fwd<Params>(params)...);
    143     }
    144 
    145   private:
    146     F f;
    147   };
    148 
    149   Own<Iface> impl;
    150 };
    151 
    152 template <typename Return, typename... Params>
    153 class ConstFunction<Return(Params...)> {
    154 public:
    155   template <typename F>
    156   inline ConstFunction(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {}
    157   ConstFunction() = default;
    158 
    159   // Make sure people don't accidentally end up wrapping a reference when they meant to return
    160   // a function.
    161   KJ_DISALLOW_COPY(ConstFunction);
    162   ConstFunction(ConstFunction&) = delete;
    163   ConstFunction& operator=(ConstFunction&) = delete;
    164   template <typename T> ConstFunction(const ConstFunction<T>&) = delete;
    165   template <typename T> ConstFunction& operator=(const ConstFunction<T>&) = delete;
    166   template <typename T> ConstFunction(const Function<T>&) = delete;
    167   template <typename T> ConstFunction& operator=(const Function<T>&) = delete;
    168   ConstFunction(ConstFunction&&) = default;
    169   ConstFunction& operator=(ConstFunction&&) = default;
    170 
    171   inline Return operator()(Params... params) const {
    172     return (*impl)(kj::fwd<Params>(params)...);
    173   }
    174 
    175   ConstFunction reference() const {
    176     // Forms a new ConstFunction of the same type that delegates to this ConstFunction by reference.
    177     // Therefore, this ConstFunction must outlive the returned ConstFunction, but otherwise they
    178     // behave exactly the same.
    179 
    180     return *impl;
    181   }
    182 
    183 private:
    184   class Iface {
    185   public:
    186     virtual Return operator()(Params... params) const = 0;
    187   };
    188 
    189   template <typename F>
    190   class Impl final: public Iface {
    191   public:
    192     explicit Impl(F&& f): f(kj::fwd<F>(f)) {}
    193 
    194     Return operator()(Params... params) const override {
    195       return f(kj::fwd<Params>(params)...);
    196     }
    197 
    198   private:
    199     F f;
    200   };
    201 
    202   Own<Iface> impl;
    203 };
    204 
    205 template <typename Return, typename... Params>
    206 class FunctionParam<Return(Params...)> {
    207 public:
    208   template <typename Func>
    209   FunctionParam(Func&& func) {
    210     typedef Wrapper<Decay<Func>> WrapperType;
    211 
    212     // All instances of Wrapper<Func> are two pointers in size: a vtable, and a Func&. So if we
    213     // allocate space for two pointers, we can construct a Wrapper<Func> in it!
    214     static_assert(sizeof(WrapperType) == sizeof(space),
    215         "expected WrapperType to be two pointers");
    216 
    217     // Even if `func` is an rvalue reference, it's OK to use it as an lvalue here, because
    218     // FunctionParam is used strictly for parameters. If we captured a temporary, we know that
    219     // temporary will not be destroyed until after the function call completes.
    220     ctor(*reinterpret_cast<WrapperType*>(space), func);
    221   }
    222 
    223   FunctionParam(const FunctionParam& other) = default;
    224   FunctionParam(FunctionParam&& other) = default;
    225   // Magically, a plain copy works.
    226 
    227   inline Return operator()(Params... params) {
    228     return (*reinterpret_cast<WrapperBase*>(space))(kj::fwd<Params>(params)...);
    229   }
    230 
    231 private:
    232   alignas(void*) char space[2 * sizeof(void*)];
    233 
    234   class WrapperBase {
    235   public:
    236     virtual Return operator()(Params... params) = 0;
    237   };
    238 
    239   template <typename Func>
    240   class Wrapper: public WrapperBase {
    241   public:
    242     Wrapper(Func& func): func(func) {}
    243 
    244     inline Return operator()(Params... params) override {
    245       return func(kj::fwd<Params>(params)...);
    246     }
    247 
    248   private:
    249     Func& func;
    250   };
    251 };
    252 
    253 namespace _ {  // private
    254 
    255 template <typename T, typename Func, typename ConstFunc>
    256 class BoundMethod {
    257 public:
    258   BoundMethod(T&& t, Func&& func, ConstFunc&& constFunc)
    259       : t(kj::fwd<T>(t)), func(kj::mv(func)), constFunc(kj::mv(constFunc)) {}
    260 
    261   template <typename... Params>
    262   auto operator()(Params&&... params) {
    263     return func(t, kj::fwd<Params>(params)...);
    264   }
    265   template <typename... Params>
    266   auto operator()(Params&&... params) const {
    267     return constFunc(t, kj::fwd<Params>(params)...);
    268   }
    269 
    270 private:
    271   T t;
    272   Func func;
    273   ConstFunc constFunc;
    274 };
    275 
    276 template <typename T, typename Func, typename ConstFunc>
    277 BoundMethod<T, Func, ConstFunc> boundMethod(T&& t, Func&& func, ConstFunc&& constFunc) {
    278   return { kj::fwd<T>(t), kj::fwd<Func>(func), kj::fwd<ConstFunc>(constFunc) };
    279 }
    280 
    281 }  // namespace _ (private)
    282 
    283 #define KJ_BIND_METHOD(obj, method) \
    284   ::kj::_::boundMethod(obj, \
    285       [](auto& s, auto&&... p) mutable { return s.method(kj::fwd<decltype(p)>(p)...); }, \
    286       [](auto& s, auto&&... p) { return s.method(kj::fwd<decltype(p)>(p)...); })
    287 // Macro that produces a functor object which forwards to the method `obj.name`.  If `obj` is an
    288 // lvalue, the functor will hold a reference to it.  If `obj` is an rvalue, the functor will
    289 // contain a copy (by move) of it. The method is allowed to be overloaded.
    290 
    291 }  // namespace kj
    292 
    293 KJ_END_HEADER