You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by mp...@apache.org on 2017/12/05 08:25:14 UTC

mesos git commit: Added `CallableOnce` class template, similar to `std::function`.

Repository: mesos
Updated Branches:
  refs/heads/master 0e3509444 -> 7beea9cbe


Added `CallableOnce` class template, similar to `std::function`.

`CallableOnce` class is similar to `std::function`, but allows it to
be called only once. Together with `lambda::partial` this provides
foundation for copy-less `defer`, `dispatch` and `Future`.

Review: https://reviews.apache.org/r/63630/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/7beea9cb
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/7beea9cb
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/7beea9cb

Branch: refs/heads/master
Commit: 7beea9cbe083caf738fb02b9d58dadf3da900f4b
Parents: 0e35094
Author: Dmitry Zhuk <dz...@twopensource.com>
Authored: Mon Dec 4 08:12:01 2017 -0800
Committer: Michael Park <mp...@apache.org>
Committed: Tue Dec 5 00:19:13 2017 -0800

----------------------------------------------------------------------
 3rdparty/stout/include/stout/lambda.hpp | 99 ++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/7beea9cb/3rdparty/stout/include/stout/lambda.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/lambda.hpp b/3rdparty/stout/include/stout/lambda.hpp
index c14241a..96586bd 100644
--- a/3rdparty/stout/include/stout/lambda.hpp
+++ b/3rdparty/stout/include/stout/lambda.hpp
@@ -15,10 +15,13 @@
 
 #include <algorithm>
 #include <functional>
+#include <memory>
 #include <type_traits>
 #include <utility>
 #include <vector>
 
+#include <glog/logging.h>
+
 #include <stout/cpp14.hpp>
 #include <stout/cpp17.hpp>
 #include <stout/result_of.hpp>
@@ -296,6 +299,102 @@ partial(F&& f, Args&&... args)
 
 #undef RETURN
 
+
+namespace internal {
+
+// Helper for invoking functional objects.
+// It needs specialization for `void` return type to ignore potentialy
+// non-`void` return value from `cpp17::invoke(f, args...)`.
+template <typename R>
+struct Invoke
+{
+  template <typename F, typename... Args>
+  R operator()(F&& f, Args&&... args)
+  {
+    return cpp17::invoke(std::forward<F>(f), std::forward<Args>(args)...);
+  }
+};
+
+
+template <>
+struct Invoke<void>
+{
+  template <typename F, typename... Args>
+  void operator()(F&& f, Args&&... args)
+  {
+    cpp17::invoke(std::forward<F>(f), std::forward<Args>(args)...);
+  }
+};
+
+} // namespace internal {
+
+
+// This is similar to `std::function`, but it can only be called once.
+// The "called once" semantics is enforced by having rvalue-ref qualifier
+// on `operator()`, so instances of `CallableOnce` must be `std::move`'d
+// in order to be invoked. Similar to `std::function`, this has heap
+// allocation overhead due to type erasure.
+//
+// Note: Heap allocation can be avoided in some cases by implementing
+// small buffer optimization. This is currently not implemented.
+template <typename F>
+class CallableOnce;
+
+
+template <typename R, typename... Args>
+class CallableOnce<R(Args...)>
+{
+public:
+  template <
+      typename F,
+      typename std::enable_if<
+          !std::is_same<F, CallableOnce>::value &&
+            (std::is_same<R, void>::value ||
+             std::is_convertible<
+                 decltype(
+                     cpp17::invoke(std::declval<F>(), std::declval<Args>()...)),
+                 R>::value),
+          int>::type = 0>
+  CallableOnce(F&& f)
+    : f(new CallableFn<typename std::decay<F>::type>(std::forward<F>(f))) {}
+
+  CallableOnce(CallableOnce&&) = default;
+  CallableOnce(const CallableOnce&) = delete;
+
+  CallableOnce& operator=(CallableOnce&&) = default;
+  CallableOnce& operator=(const CallableOnce&) = delete;
+
+  template <typename... Args_>
+  R operator()(Args_&&... args) &&
+  {
+    CHECK(f != nullptr);
+    return std::move(*f)(std::forward<Args_>(args)...);
+  }
+
+private:
+  struct Callable
+  {
+    virtual ~Callable() = default;
+    virtual R operator()(Args...) && = 0;
+  };
+
+  template <typename F>
+  struct CallableFn : Callable
+  {
+    F f;
+
+    CallableFn(const F& f) : f(f) {}
+    CallableFn(F&& f) : f(std::move(f)) {}
+
+    virtual R operator()(Args... args) &&
+    {
+      return internal::Invoke<R>{}(std::move(f), std::forward<Args>(args)...);
+    }
+  };
+
+  std::unique_ptr<Callable> f;
+};
+
 } // namespace lambda {