You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					278 lines
				
				9.0 KiB
			
		
		
			
		
	
	
					278 lines
				
				9.0 KiB
			| 
								 
											8 years ago
										 
									 | 
							
								// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
							 | 
						||
| 
								 | 
							
								// Licensed under the MIT License:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Permission is hereby granted, free of charge, to any person obtaining a copy
							 | 
						||
| 
								 | 
							
								// of this software and associated documentation files (the "Software"), to deal
							 | 
						||
| 
								 | 
							
								// in the Software without restriction, including without limitation the rights
							 | 
						||
| 
								 | 
							
								// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
							 | 
						||
| 
								 | 
							
								// copies of the Software, and to permit persons to whom the Software is
							 | 
						||
| 
								 | 
							
								// furnished to do so, subject to the following conditions:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// The above copyright notice and this permission notice shall be included in
							 | 
						||
| 
								 | 
							
								// all copies or substantial portions of the Software.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
							 | 
						||
| 
								 | 
							
								// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
							 | 
						||
| 
								 | 
							
								// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
							 | 
						||
| 
								 | 
							
								// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
							 | 
						||
| 
								 | 
							
								// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
							 | 
						||
| 
								 | 
							
								// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
							 | 
						||
| 
								 | 
							
								// THE SOFTWARE.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef KJ_FUNCTION_H_
							 | 
						||
| 
								 | 
							
								#define KJ_FUNCTION_H_
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(__GNUC__) && !KJ_HEADER_WARNINGS
							 | 
						||
| 
								 | 
							
								#pragma GCC system_header
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "memory.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace kj {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Signature>
							 | 
						||
| 
								 | 
							
								class Function;
							 | 
						||
| 
								 | 
							
								// Function wrapper using virtual-based polymorphism.  Use this when template polymorphism is
							 | 
						||
| 
								 | 
							
								// not possible.  You can, for example, accept a Function as a parameter:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//     void setFilter(Function<bool(const Widget&)> filter);
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// The caller of `setFilter()` may then pass any callable object as the parameter.  The callable
							 | 
						||
| 
								 | 
							
								// object does not have to have the exact signature specified, just one that is "compatible" --
							 | 
						||
| 
								 | 
							
								// i.e. the return type is covariant and the parameters are contravariant.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Unlike `std::function`, `kj::Function`s are movable but not copyable, just like `kj::Own`.  This
							 | 
						||
| 
								 | 
							
								// is to avoid unexpected heap allocation or slow atomic reference counting.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// When a `Function` is constructed from an lvalue, it captures only a reference to the value.
							 | 
						||
| 
								 | 
							
								// When constructed from an rvalue, it invokes the value's move constructor.  So, for example:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//     struct AddN {
							 | 
						||
| 
								 | 
							
								//       int n;
							 | 
						||
| 
								 | 
							
								//       int operator(int i) { return i + n; }
							 | 
						||
| 
								 | 
							
								//     }
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//     Function<int(int, int)> f1 = AddN{2};
							 | 
						||
| 
								 | 
							
								//     // f1 owns an instance of AddN.  It may safely be moved out
							 | 
						||
| 
								 | 
							
								//     // of the local scope.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//     AddN adder(2);
							 | 
						||
| 
								 | 
							
								//     Function<int(int, int)> f2 = adder;
							 | 
						||
| 
								 | 
							
								//     // f2 contains a reference to `adder`.  Thus, it becomes invalid
							 | 
						||
| 
								 | 
							
								//     // when `adder` goes out-of-scope.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//     AddN adder2(2);
							 | 
						||
| 
								 | 
							
								//     Function<int(int, int)> f3 = kj::mv(adder2);
							 | 
						||
| 
								 | 
							
								//     // f3 owns an insatnce of AddN moved from `adder2`.  f3 may safely
							 | 
						||
| 
								 | 
							
								//     // be moved out of the local scope.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Additionally, a Function may be bound to a class method using KJ_BIND_METHOD(object, methodName).
							 | 
						||
| 
								 | 
							
								// For example:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//     class Printer {
							 | 
						||
| 
								 | 
							
								//     public:
							 | 
						||
| 
								 | 
							
								//       void print(int i);
							 | 
						||
| 
								 | 
							
								//       void print(kj::StringPtr s);
							 | 
						||
| 
								 | 
							
								//     };
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//     Printer p;
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//     Function<void(uint)> intPrinter = KJ_BIND_METHOD(p, print);
							 | 
						||
| 
								 | 
							
								//     // Will call Printer::print(int).
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//     Function<void(const char*)> strPrinter = KJ_BIND_METHOD(p, print);
							 | 
						||
| 
								 | 
							
								//     // Will call Printer::print(kj::StringPtr).
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Notice how KJ_BIND_METHOD is able to figure out which overload to use depending on the kind of
							 | 
						||
| 
								 | 
							
								// Function it is binding to.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Signature>
							 | 
						||
| 
								 | 
							
								class ConstFunction;
							 | 
						||
| 
								 | 
							
								// Like Function, but wraps a "const" (i.e. thread-safe) call.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Return, typename... Params>
							 | 
						||
| 
								 | 
							
								class Function<Return(Params...)> {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  template <typename F>
							 | 
						||
| 
								 | 
							
								  inline Function(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {}
							 | 
						||
| 
								 | 
							
								  Function() = default;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Make sure people don't accidentally end up wrapping a reference when they meant to return
							 | 
						||
| 
								 | 
							
								  // a function.
							 | 
						||
| 
								 | 
							
								  KJ_DISALLOW_COPY(Function);
							 | 
						||
| 
								 | 
							
								  Function(Function&) = delete;
							 | 
						||
| 
								 | 
							
								  Function& operator=(Function&) = delete;
							 | 
						||
| 
								 | 
							
								  template <typename T> Function(const Function<T>&) = delete;
							 | 
						||
| 
								 | 
							
								  template <typename T> Function& operator=(const Function<T>&) = delete;
							 | 
						||
| 
								 | 
							
								  template <typename T> Function(const ConstFunction<T>&) = delete;
							 | 
						||
| 
								 | 
							
								  template <typename T> Function& operator=(const ConstFunction<T>&) = delete;
							 | 
						||
| 
								 | 
							
								  Function(Function&&) = default;
							 | 
						||
| 
								 | 
							
								  Function& operator=(Function&&) = default;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  inline Return operator()(Params... params) {
							 | 
						||
| 
								 | 
							
								    return (*impl)(kj::fwd<Params>(params)...);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Function reference() {
							 | 
						||
| 
								 | 
							
								    // Forms a new Function of the same type that delegates to this Function by reference.
							 | 
						||
| 
								 | 
							
								    // Therefore, this Function must outlive the returned Function, but otherwise they behave
							 | 
						||
| 
								 | 
							
								    // exactly the same.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return *impl;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  class Iface {
							 | 
						||
| 
								 | 
							
								  public:
							 | 
						||
| 
								 | 
							
								    virtual Return operator()(Params... params) = 0;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <typename F>
							 | 
						||
| 
								 | 
							
								  class Impl final: public Iface {
							 | 
						||
| 
								 | 
							
								  public:
							 | 
						||
| 
								 | 
							
								    explicit Impl(F&& f): f(kj::fwd<F>(f)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Return operator()(Params... params) override {
							 | 
						||
| 
								 | 
							
								      return f(kj::fwd<Params>(params)...);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  private:
							 | 
						||
| 
								 | 
							
								    F f;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Own<Iface> impl;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Return, typename... Params>
							 | 
						||
| 
								 | 
							
								class ConstFunction<Return(Params...)> {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  template <typename F>
							 | 
						||
| 
								 | 
							
								  inline ConstFunction(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {}
							 | 
						||
| 
								 | 
							
								  ConstFunction() = default;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Make sure people don't accidentally end up wrapping a reference when they meant to return
							 | 
						||
| 
								 | 
							
								  // a function.
							 | 
						||
| 
								 | 
							
								  KJ_DISALLOW_COPY(ConstFunction);
							 | 
						||
| 
								 | 
							
								  ConstFunction(ConstFunction&) = delete;
							 | 
						||
| 
								 | 
							
								  ConstFunction& operator=(ConstFunction&) = delete;
							 | 
						||
| 
								 | 
							
								  template <typename T> ConstFunction(const ConstFunction<T>&) = delete;
							 | 
						||
| 
								 | 
							
								  template <typename T> ConstFunction& operator=(const ConstFunction<T>&) = delete;
							 | 
						||
| 
								 | 
							
								  template <typename T> ConstFunction(const Function<T>&) = delete;
							 | 
						||
| 
								 | 
							
								  template <typename T> ConstFunction& operator=(const Function<T>&) = delete;
							 | 
						||
| 
								 | 
							
								  ConstFunction(ConstFunction&&) = default;
							 | 
						||
| 
								 | 
							
								  ConstFunction& operator=(ConstFunction&&) = default;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  inline Return operator()(Params... params) const {
							 | 
						||
| 
								 | 
							
								    return (*impl)(kj::fwd<Params>(params)...);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ConstFunction reference() const {
							 | 
						||
| 
								 | 
							
								    // Forms a new ConstFunction of the same type that delegates to this ConstFunction by reference.
							 | 
						||
| 
								 | 
							
								    // Therefore, this ConstFunction must outlive the returned ConstFunction, but otherwise they
							 | 
						||
| 
								 | 
							
								    // behave exactly the same.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return *impl;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  class Iface {
							 | 
						||
| 
								 | 
							
								  public:
							 | 
						||
| 
								 | 
							
								    virtual Return operator()(Params... params) const = 0;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <typename F>
							 | 
						||
| 
								 | 
							
								  class Impl final: public Iface {
							 | 
						||
| 
								 | 
							
								  public:
							 | 
						||
| 
								 | 
							
								    explicit Impl(F&& f): f(kj::fwd<F>(f)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Return operator()(Params... params) const override {
							 | 
						||
| 
								 | 
							
								      return f(kj::fwd<Params>(params)...);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  private:
							 | 
						||
| 
								 | 
							
								    F f;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Own<Iface> impl;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if 1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace _ {  // private
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T, typename Signature, Signature method>
							 | 
						||
| 
								 | 
							
								class BoundMethod;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T, typename Return, typename... Params, Return (Decay<T>::*method)(Params...)>
							 | 
						||
| 
								 | 
							
								class BoundMethod<T, Return (Decay<T>::*)(Params...), method> {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  BoundMethod(T&& t): t(kj::fwd<T>(t)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Return operator()(Params&&... params) {
							 | 
						||
| 
								 | 
							
								    return (t.*method)(kj::fwd<Params>(params)...);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  T t;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T, typename Return, typename... Params,
							 | 
						||
| 
								 | 
							
								          Return (Decay<T>::*method)(Params...) const>
							 | 
						||
| 
								 | 
							
								class BoundMethod<T, Return (Decay<T>::*)(Params...) const, method> {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  BoundMethod(T&& t): t(kj::fwd<T>(t)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Return operator()(Params&&... params) const {
							 | 
						||
| 
								 | 
							
								    return (t.*method)(kj::fwd<Params>(params)...);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  T t;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace _ (private)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define KJ_BIND_METHOD(obj, method) \
							 | 
						||
| 
								 | 
							
								  ::kj::_::BoundMethod<KJ_DECLTYPE_REF(obj), \
							 | 
						||
| 
								 | 
							
								                       decltype(&::kj::Decay<decltype(obj)>::method), \
							 | 
						||
| 
								 | 
							
								                       &::kj::Decay<decltype(obj)>::method>(obj)
							 | 
						||
| 
								 | 
							
								// Macro that produces a functor object which forwards to the method `obj.name`.  If `obj` is an
							 | 
						||
| 
								 | 
							
								// lvalue, the functor will hold a reference to it.  If `obj` is an rvalue, the functor will
							 | 
						||
| 
								 | 
							
								// contain a copy (by move) of it.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// The current implementation requires that the method is not overloaded.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// TODO(someday):  C++14's generic lambdas may be able to simplify this code considerably, and
							 | 
						||
| 
								 | 
							
								//   probably make it work with overloaded methods.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								// Here's a better implementation of the above that doesn't work with GCC (but does with Clang)
							 | 
						||
| 
								 | 
							
								// because it uses a local class with a template method.  Sigh.  This implementation supports
							 | 
						||
| 
								 | 
							
								// overloaded methods.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define KJ_BIND_METHOD(obj, method) \
							 | 
						||
| 
								 | 
							
								  ({ \
							 | 
						||
| 
								 | 
							
								    typedef KJ_DECLTYPE_REF(obj) T; \
							 | 
						||
| 
								 | 
							
								    class F { \
							 | 
						||
| 
								 | 
							
								    public: \
							 | 
						||
| 
								 | 
							
								      inline F(T&& t): t(::kj::fwd<T>(t)) {} \
							 | 
						||
| 
								 | 
							
								      template <typename... Params> \
							 | 
						||
| 
								 | 
							
								      auto operator()(Params&&... params) \
							 | 
						||
| 
								 | 
							
								          -> decltype(::kj::instance<T>().method(::kj::fwd<Params>(params)...)) { \
							 | 
						||
| 
								 | 
							
								        return t.method(::kj::fwd<Params>(params)...); \
							 | 
						||
| 
								 | 
							
								      } \
							 | 
						||
| 
								 | 
							
								    private: \
							 | 
						||
| 
								 | 
							
								      T t; \
							 | 
						||
| 
								 | 
							
								    }; \
							 | 
						||
| 
								 | 
							
								    (F(obj)); \
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								// Macro that produces a functor object which forwards to the method `obj.name`.  If `obj` is an
							 | 
						||
| 
								 | 
							
								// lvalue, the functor will hold a reference to it.  If `obj` is an rvalue, the functor will
							 | 
						||
| 
								 | 
							
								// contain a copy (by move) of it.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace kj
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  // KJ_FUNCTION_H_
							 |