Subprocess: allow non-copyable callbacks
authorSven Over <over@fb.com>
Fri, 22 Apr 2016 18:00:39 +0000 (11:00 -0700)
committerFacebook Github Bot 6 <facebook-github-bot-6-bot@fb.com>
Fri, 22 Apr 2016 18:05:31 +0000 (11:05 -0700)
Summary:Instead of std::function<bool(int, int)>, use folly::Function to
pass callbacks to Subprocess::communicate. This makes it possible
to pass non-copyable callables, which is especially interesting
because Subprocess::readLinesCallback returns a non-copyable
object.

This diff also fixes the forwarding of the callback passed to
readLinesCallback in case you pass an lvalue reference.

Reviewed By: snarkmaster

Differential Revision: D3169956

fb-gh-sync-id: 7a906f9a3ab50502fc04e0d83a23ca5e0201bb3e
fbshipit-source-id: 7a906f9a3ab50502fc04e0d83a23ca5e0201bb3e

folly/Subprocess.h

index 2b6cbffc864f697d705b6ee7735750ccc550df95..e922ee0d261a8cfdeb348b95cbafb2d215eb1484 100644 (file)
 #include <folly/Exception.h>
 #include <folly/File.h>
 #include <folly/FileUtil.h>
+#include <folly/Function.h>
 #include <folly/gen/String.h>
 #include <folly/io/IOBufQueue.h>
 #include <folly/MapUtil.h>
@@ -613,7 +614,7 @@ class Subprocess {
    * expensive implementation choice, in order to make closeParentFd()
    * thread-safe.
    */
-  typedef std::function<bool(int, int)> FdCallback;
+  using FdCallback = folly::Function<bool(int, int)>;
   void communicate(FdCallback readCallback, FdCallback writeCallback);
 
   /**
@@ -622,17 +623,13 @@ class Subprocess {
    * descriptors.  Use the readLinesCallback() helper to get template
    * deduction.  For example:
    *
-   *   auto read_cb = Subprocess::readLinesCallback(
-   *     [](int fd, folly::StringPiece s) {
-   *       std::cout << fd << " said: " << s;
-   *       return false;  // Keep reading from the child
-   *     }
-   *   );
    *   subprocess.communicate(
-   *     // ReadLinesCallback contains StreamSplitter contains IOBuf, making
-   *     // it noncopyable, whereas std::function must be copyable.  So, we
-   *     // keep the callback in a local, and instead pass a reference.
-   *     std::ref(read_cb),
+   *     Subprocess::readLinesCallback(
+   *       [](int fd, folly::StringPiece s) {
+   *         std::cout << fd << " said: " << s;
+   *         return false;  // Keep reading from the child
+   *       }
+   *     ),
    *     [](int pdf, int cfd){ return true; }  // Don't write to the child
    *   );
    *
@@ -706,14 +703,14 @@ class Subprocess {
 
   // Helper to enable template deduction
   template <class Callback>
-  static ReadLinesCallback<Callback> readLinesCallback(
+  static auto readLinesCallback(
       Callback&& fdLineCb,
-      uint64_t maxLineLength = 0,  // No line length limit by default
+      uint64_t maxLineLength = 0, // No line length limit by default
       char delimiter = '\n',
-      uint64_t bufSize = 1024) {
-    return ReadLinesCallback<Callback>(
-      std::move(fdLineCb), maxLineLength, delimiter, bufSize
-    );
+      uint64_t bufSize = 1024)
+      -> ReadLinesCallback<typename std::decay<Callback>::type> {
+    return ReadLinesCallback<typename std::decay<Callback>::type>(
+        std::forward<Callback>(fdLineCb), maxLineLength, delimiter, bufSize);
   }
 
   /**