Author: brane
Date: Tue Jan  8 16:55:31 2019
New Revision: 1850774

URL: http://svn.apache.org/viewvc?rev=1850774&view=rev
Log:
Invent a model of asynchronous operations in SVN++.

[in subversion/bindings/cxx]
* README: Document a warning about the current async op model.

* svnxx/client/context.hpp
  (detail::context_ptr): Make this a shared pointer because asynchronous
   operations have to hold on to a weak reference to the context.
  (detail::weak_context_ptr): New.

* svnxx/client/status.hpp: Don't include <future>, use detail/future.hpp.
  (client::status): Pass revision by const-reference. Update docstring.
  (client::async::status): New.

* svnxx/detail/future.hpp: New. Provides std::future-like tools for SVN++.
* src/future.cpp,
  src/private/future_private.hpp: New.
* src/private/client_context_private.hpp
  (impl::unwrap): Return a shared pointer to the client context.
* src/private.hpp: Include private/future_private.hpp.

* src/client_status.cpp
  (impl::(anon)::status_func): Moved here so that it can be used from
   impl::status. Check that the wrapped callback functor is not null
   before invoking it.
  (impl::status): New; common implementation for the status operation.
  (client::status): Use impl::status. Keep the client context alive.
  (client::async::status): New.

* tests/test_client_status.cpp
  (working_copy_root, status_callback): Move to anonymous scope.
  (async_example): New test case.

Added:
    subversion/trunk/subversion/bindings/cxx/include/svnxx/detail/future.hpp   
(with props)
    subversion/trunk/subversion/bindings/cxx/src/future.cpp   (with props)
    subversion/trunk/subversion/bindings/cxx/src/private/future_private.hpp   
(with props)
Modified:
    subversion/trunk/subversion/bindings/cxx/README
    subversion/trunk/subversion/bindings/cxx/include/svnxx/client/context.hpp
    subversion/trunk/subversion/bindings/cxx/include/svnxx/client/status.hpp
    subversion/trunk/subversion/bindings/cxx/src/client_status.cpp
    subversion/trunk/subversion/bindings/cxx/src/private.hpp
    
subversion/trunk/subversion/bindings/cxx/src/private/client_context_private.hpp
    subversion/trunk/subversion/bindings/cxx/tests/test_client_status.cpp

Modified: subversion/trunk/subversion/bindings/cxx/README
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/README?rev=1850774&r1=1850773&r2=1850774&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/README (original)
+++ subversion/trunk/subversion/bindings/cxx/README Tue Jan  8 16:55:31 2019
@@ -129,3 +129,19 @@ with the single header file
     .../src/aprwrap.hpp
 
 importing all relevant headers from that directory.
+
+====================================================================
+
+IMPLEMENTATION NOTES
+====================
+
+Asynchronous Operations (TODO)
+------------------------------
+
+In the current model of asyncrhonous operations, we do not protect
+against using the same svn_client_ctx_t object from multiple
+threads. This _should_ be safe as long as the callback
+implementations are aware of it, but we should consider changing the
+design so that whilst svn::client::context can be shared, we create
+the actual svn_client_ctx_t on the fly for each operation --
+similarly to how we create a the scratch pool.

Modified: 
subversion/trunk/subversion/bindings/cxx/include/svnxx/client/context.hpp
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/include/svnxx/client/context.hpp?rev=1850774&r1=1850773&r2=1850774&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/include/svnxx/client/context.hpp 
(original)
+++ subversion/trunk/subversion/bindings/cxx/include/svnxx/client/context.hpp 
Tue Jan  8 16:55:31 2019
@@ -34,7 +34,8 @@ namespace client {
 
 namespace detail {
 class context;
-using context_ptr = std::unique_ptr<context>;
+using context_ptr = std::shared_ptr<context>;
+using weak_context_ptr = std::weak_ptr<context>;
 } // namespace detail
 
 /**

Modified: 
subversion/trunk/subversion/bindings/cxx/include/svnxx/client/status.hpp
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/include/svnxx/client/status.hpp?rev=1850774&r1=1850773&r2=1850774&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/include/svnxx/client/status.hpp 
(original)
+++ subversion/trunk/subversion/bindings/cxx/include/svnxx/client/status.hpp 
Tue Jan  8 16:55:31 2019
@@ -27,8 +27,8 @@
 
 #include <cstdint>
 #include <functional>
-#include <future>
 
+#include "svnxx/detail/future.hpp"
 #include "svnxx/client/context.hpp"
 
 #include "svnxx/depth.hpp"
@@ -82,8 +82,8 @@ inline status_flags operator|(status_fla
 }
 
 /**
- * @brief Perform a status walk on @a path.
- * @see svn_client_status6
+ * @ingroup svnxx_client
+ * @brief Perform a status operation on @a path.
  * @param ctx the #context object to use for this operation
  * @param path the (root) path for the status walk.
  * @param rev the revision to use when @c check_out_of_date is set in @a flags
@@ -91,12 +91,45 @@ inline status_flags operator|(status_fla
  * @param flags a combination of @c status_flags
  * @param callback a function that will be called for each status target
  * @warning TODO: Work in progress
+ * @see svn_client_status6
  */
 revision::number
 status(context& ctx, const char* path,
-       revision rev, depth depth, status_flags flags,
+       const revision& rev, depth depth, status_flags flags,
+       status_callback callback);
+
+namespace async {
+
+/**
+ * @ingroup svnxx_client
+ * @brief Perform an asynchronous status operation on @a path.
+ *
+ * Behaves as if svn::client::status() were invoked through
+ * <tt>std::async()</tt>, but also maintains the lifetime of
+ * internal state relevant to the status operation.
+ *
+ * @warning Any callbacks regietered in the context @a ctx, as well
+ *          as the status @a callback itself, may be called in the
+ *          context of a different thread than the one that created
+ *          this asynchronous operation.
+ */
+svnxx::detail::future<revision::number>
+status(std::launch policy, context& ctx, const char* path,
+       const revision& rev, depth depth_, status_flags flags,
+       status_callback callback);
+
+/**
+ * @overload
+ * @ingroup svnxx_client
+ * @note Uses the <tt>std::launch</tt> @a policy set to
+ *       <tt>std::launch::async|std::launch::deferred</tt>.
+ */
+svnxx::detail::future<revision::number>
+status(context& ctx, const char* path,
+       const revision& rev, depth depth_, status_flags flags,
        status_callback callback);
 
+} // namespace async
 } // namespace client
 } // namespace svnxx
 } // namespace subversion

Added: subversion/trunk/subversion/bindings/cxx/include/svnxx/detail/future.hpp
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/include/svnxx/detail/future.hpp?rev=1850774&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/include/svnxx/detail/future.hpp 
(added)
+++ subversion/trunk/subversion/bindings/cxx/include/svnxx/detail/future.hpp 
Tue Jan  8 16:55:31 2019
@@ -0,0 +1,175 @@
+/**
+ * @file svnxx/detail/future.hpp
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+#ifndef SVNXX_DETAIL_FUTURE_HPP
+#define SVNXX_DETAIL_FUTURE_HPP
+
+#include <future>
+#include <memory>
+
+namespace apache {
+namespace subversion {
+namespace svnxx {
+namespace detail {
+namespace future_ {
+
+// Forward delcaration of the future result context.
+class result;
+using shared_ptr = std::shared_ptr<result>;
+using unique_ptr = std::unique_ptr<result>;
+
+
+// Base class for template shared_future.
+class shared_future_base
+{
+protected:
+  shared_future_base() noexcept {}
+
+  shared_future_base(const shared_future_base& that)
+    : shared_result(that.shared_result)
+    {}
+
+  shared_future_base(shared_future_base&& that)
+    : shared_result(std::move(that.shared_result))
+    {}
+
+  explicit shared_future_base(shared_ptr shared_result_)
+    : shared_result(shared_result_)
+    {}
+
+private:
+  shared_ptr shared_result;
+};
+
+// Template forward declaration for shared_future constructor.
+template<typename T> class future;
+
+/**
+ * @ingroup svnxx_detail
+ * @brief like <tt>std::shared_future</tt>, but also maintains
+ * internal state relevant to the asynchronous SVN++ operation.
+ */
+template<typename T>
+class shared_future : private std::shared_future<T>,
+                      private shared_future_base
+{
+protected:
+  using inherited = std::shared_future<T>;
+
+  shared_future(inherited&& that, shared_ptr shared_result) noexcept
+    : inherited(that), shared_future_base(shared_result)
+    {}
+
+public:
+  shared_future() noexcept {}
+
+  shared_future(const shared_future& that) noexcept
+    : inherited(that), shared_future_base(that)
+    {}
+
+  shared_future(shared_future&& that) noexcept
+    : inherited(std::move(that)), shared_future_base(std::move(that))
+    {}
+
+  shared_future(future<T>&& that) noexcept;
+
+  using inherited::get;
+  using inherited::valid;
+  using inherited::wait;
+  using inherited::wait_for;
+  using inherited::wait_until;
+};
+
+
+// Base class for template future.
+class future_base
+{
+protected:
+  future_base() noexcept;
+  ~future_base() noexcept;
+  future_base(future_base&& that) noexcept;
+  future_base(const future_base&) = delete;
+  explicit future_base(unique_ptr&& unique_result_) noexcept;
+
+  shared_ptr share() noexcept;
+
+private:
+  unique_ptr unique_result;
+};
+
+/**
+ * @ingroup svnxx_detail
+ * @brief like <tt>std::future</tt>, but also maintains internal
+ * state relevant to the asynchronous SVN++ operation.
+ */
+template<typename T>
+class future : private std::future<T>,
+               private future_base
+{
+  // shared_future constructor must be able to access our base classes.
+  friend class shared_future<T>;
+
+protected:
+  using inherited = std::future<T>;
+
+  future(inherited&& that, unique_ptr&& unique_result) noexcept
+    : inherited(std::move(that)), future_base(std::move(unique_result))
+    {}
+
+public:
+  future() noexcept {}
+
+  future(future&& that) noexcept
+    : inherited(std::move(that)), future_base(std::move(that))
+    {}
+
+  shared_future<T> share() noexcept
+    {
+      return shared_future<T>(std::move(*this));
+    }
+
+  using inherited::get;
+  using inherited::valid;
+  using inherited::wait;
+  using inherited::wait_for;
+  using inherited::wait_until;
+};
+
+// Implement the constructor here since it has to see the whole future class.
+template<typename T>
+inline shared_future<T>::shared_future(future<T>&& that) noexcept
+  : inherited(std::move(that)), shared_future_base(that.future_base::share())
+{}
+
+} // namespace future_
+
+template<typename T> using future = future_::future<T>;
+template<typename T> using shared_future = future_::shared_future<T>;
+
+} // namespace detail
+} // namespace svnxx
+} // namespace subversion
+} // namespace apache
+
+#endif  // SVNXX_DETAIL_FUTURE_HPP

Propchange: 
subversion/trunk/subversion/bindings/cxx/include/svnxx/detail/future.hpp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/trunk/subversion/bindings/cxx/src/client_status.cpp
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/src/client_status.cpp?rev=1850774&r1=1850773&r2=1850774&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/src/client_status.cpp (original)
+++ subversion/trunk/subversion/bindings/cxx/src/client_status.cpp Tue Jan  8 
16:55:31 2019
@@ -31,9 +31,13 @@
 namespace apache {
 namespace subversion {
 namespace svnxx {
-namespace client {
 
+namespace impl {
 namespace {
+using status_notification = client::status_notification;
+using status_callback = client::status_callback;
+using status_flags = client::status_flags;
+
 struct status_func
 {
   status_callback& proxy;
@@ -42,14 +46,17 @@ struct status_func
                                const svn_client_status_t* /*status*/,
                                apr_pool_t* /*scratch_pool*/)
     {
-      try
-        {
-          const auto self = static_cast<status_func*>(baton);
-          self->proxy(path, status_notification{});
-        }
-      catch (const stop_iteration&)
+      const auto self = static_cast<status_func*>(baton);
+      if (self->proxy)
         {
-          return impl::iteration_stopped();
+          try
+            {
+              self->proxy(path, status_notification{});
+            }
+          catch (const stop_iteration&)
+            {
+              return impl::iteration_stopped();
+            }
         }
       return SVN_NO_ERROR;
     }
@@ -57,19 +64,16 @@ struct status_func
 } // anonymous namespace
 
 revision::number
-status(context& ctx_, const char* path,
-       revision rev_, depth depth, status_flags flags,
-       status_callback callback_)
+status(svn_client_ctx_t* ctx, const char* path,
+       const svn_opt_revision_t* rev, depth depth_, status_flags flags,
+       status_callback callback_, apr_pool_t* scratch_pool)
 {
-  const auto& ctx = impl::unwrap(ctx_);
-  const auto rev = impl::convert(rev_);
-  const apr::pool scratch_pool(&ctx.get_pool());
   status_func callback{callback_};
   svn_revnum_t result;
 
   impl::checked_call(
-      svn_client_status6(&result, ctx.get_ctx(), path, &rev,
-                         impl::convert(depth),
+      svn_client_status6(&result, ctx, path, rev,
+                         impl::convert(depth_),
                          bool(flags & status_flags::get_all),
                          bool(flags & status_flags::check_out_of_date),
                          bool(flags & status_flags::check_working_copy),
@@ -78,11 +82,61 @@ status(context& ctx_, const char* path,
                          bool(flags & status_flags::depth_as_sticky),
                          nullptr, // TODO: changelists,
                          status_func::callback, &callback,
-                         scratch_pool.get()
-                         ));
+                         scratch_pool));
   return revision::number(result);
 }
 
+} // namespace impl
+namespace client {
+
+revision::number
+status(context& ctx_, const char* path,
+       const revision& rev_, depth depth_, status_flags flags,
+       status_callback callback)
+{
+  const auto ctx = impl::unwrap(ctx_);
+  const auto rev = impl::convert(rev_);
+  const apr::pool scratch_pool(&ctx->get_pool());
+  return impl::status(ctx->get_ctx(), path, &rev, depth_, flags,
+                      callback, scratch_pool.get());
+}
+
+namespace async {
+
+svnxx::detail::future<revision::number>
+status(std::launch policy, context& ctx_, const char* path,
+       const revision& rev_, depth depth_, status_flags flags,
+       status_callback callback)
+{
+  detail::weak_context_ptr weak_ctx = impl::unwrap(ctx_);
+  return impl::future<revision::number>(
+      std::async(
+          policy,
+          [weak_ctx, path, rev_, depth_, flags, callback]
+            {
+              auto ctx = weak_ctx.lock();
+              if (!ctx)
+                return revision::number::invalid;
+
+              const auto rev = impl::convert(rev_);
+              const apr::pool scratch_pool(&ctx->get_pool());
+
+              return impl::status(ctx->get_ctx(), path, &rev, depth_, flags,
+                                  callback, scratch_pool.get());
+            }),
+      impl::make_future_result());
+}
+
+svnxx::detail::future<revision::number>
+status(context& ctx_, const char* path,
+       const revision& rev_, depth depth_, status_flags flags,
+       status_callback callback)
+{
+  constexpr std::launch policy = std::launch::async | std::launch::deferred;
+  return status(policy, ctx_, path, rev_, depth_, flags, callback);
+}
+
+} // namespace async
 } // namespace client
 } // namespace svnxx
 } // namespace subversion

Added: subversion/trunk/subversion/bindings/cxx/src/future.cpp
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/src/future.cpp?rev=1850774&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/src/future.cpp (added)
+++ subversion/trunk/subversion/bindings/cxx/src/future.cpp Tue Jan  8 16:55:31 
2019
@@ -0,0 +1,52 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+#include "private/future_private.hpp"
+
+namespace apache {
+namespace subversion {
+namespace svnxx {
+namespace detail {
+namespace future_ {
+
+future_base::future_base() noexcept {}
+future_base::~future_base() noexcept {}
+
+future_base::future_base(future_base&& that) noexcept
+  : future_base(std::move(that.unique_result))
+{}
+
+future_base::future_base(unique_ptr&& unique_result_) noexcept
+  : unique_result(std::move(unique_result_))
+{}
+
+shared_ptr future_base::share() noexcept
+{
+  return shared_ptr(unique_result.release());
+}
+
+} // namespace future_
+} // namespace detail
+} // namespace svnxx
+} // namespace subversion
+} // namespace apache

Propchange: subversion/trunk/subversion/bindings/cxx/src/future.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/trunk/subversion/bindings/cxx/src/private.hpp
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/src/private.hpp?rev=1850774&r1=1850773&r2=1850774&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/src/private.hpp (original)
+++ subversion/trunk/subversion/bindings/cxx/src/private.hpp Tue Jan  8 
16:55:31 2019
@@ -26,6 +26,7 @@
 
 #include "private/depth_private.hpp"
 #include "private/exception_private.hpp"
+#include "private/future_private.hpp"
 #include "private/revision_private.hpp"
 #include "private/strings_private.hpp"
 #include "private/tristate_private.hpp"

Modified: 
subversion/trunk/subversion/bindings/cxx/src/private/client_context_private.hpp
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/src/private/client_context_private.hpp?rev=1850774&r1=1850773&r2=1850774&view=diff
==============================================================================
--- 
subversion/trunk/subversion/bindings/cxx/src/private/client_context_private.hpp 
(original)
+++ 
subversion/trunk/subversion/bindings/cxx/src/private/client_context_private.hpp 
Tue Jan  8 16:55:31 2019
@@ -66,14 +66,17 @@ private:
 namespace impl {
 
 // TODO: document this
-inline client::detail::context& unwrap(client::context& ctx)
+inline client::detail::context_ptr unwrap(client::context& ctx)
 {
   struct context_wrapper final : public client::context
   {
-    using inherited::get;
+    inherited get() const noexcept
+      {
+        return *this;
+      }
   };
 
-  return *static_cast<context_wrapper&>(ctx).get();
+  return static_cast<context_wrapper&>(ctx).get();
 }
 
 } // namesapce impl

Added: subversion/trunk/subversion/bindings/cxx/src/private/future_private.hpp
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/src/private/future_private.hpp?rev=1850774&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/src/private/future_private.hpp 
(added)
+++ subversion/trunk/subversion/bindings/cxx/src/private/future_private.hpp Tue 
Jan  8 16:55:31 2019
@@ -0,0 +1,110 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+#ifndef SVNXX_PRIVATE_FUTURE_HPP
+#define SVNXX_PRIVATE_FUTURE_HPP
+
+#include "svnxx/detail/future.hpp"
+
+#include "../private/init_private.hpp"
+#include "../aprwrap.hpp"
+
+namespace apache {
+namespace subversion {
+namespace svnxx {
+namespace detail {
+namespace future_ {
+
+
+// Encapsulates a result pool that will contain pool-allocated
+// objects returned from asynchronous operations. Consequently,
+// keeps a reference to the global state that holds the root pool
+// that is the parent of this result pool.
+class result
+{
+public:
+  explicit result(const detail::global_state::ptr& state_)
+    : state(state_),
+      result_pool(state_)
+    {}
+
+  apr::pool& get_pool() noexcept
+    {
+      return result_pool;
+    }
+
+private:
+  const detail::global_state::ptr state;
+  apr::pool result_pool;
+};
+
+} // namespace future_
+} // namespace detail
+namespace impl {
+
+
+// Creates a detail::future_::result pointer for initializing
+// detail::future objects.
+inline detail::future_::unique_ptr
+make_future_result(const detail::global_state::ptr& state)
+{
+  using namespace detail::future_;
+  return unique_ptr(new result(state));
+}
+
+// Creates a null detail::future_::result pointer for cases where we
+// do not need a result pool.
+inline detail::future_::unique_ptr
+make_future_result()
+{
+  return detail::future_::unique_ptr();
+}
+
+
+// Wrapper for detail::future with public constructor.
+template<typename T>
+struct future final : public detail::future_::future<T>
+{
+  using inherited = typename detail::future_::future<T>::inherited;
+  future(inherited that, detail::future_::unique_ptr&& ctx) noexcept
+    : detail::future_::future<T>(std::move(that), std::move(ctx))
+    {}
+};
+
+
+// Wrapper for detail::shared_future with public constructor.
+template<typename T>
+struct shared_future final : public detail::future_::shared_future<T>
+{
+  using inherited = typename detail::future_::shared_future<T>::inherited;
+  shared_future(inherited that, detail::future_::shared_ptr ctx) noexcept
+    : detail::future_::shared_future<T>(std::move(that), ctx)
+    {}
+};
+
+} // namespace impl
+} // namespace svnxx
+} // namespace subversion
+} // namespace apache
+
+#endif // SVNXX_PRIVATE_FUTURE_HPP

Propchange: 
subversion/trunk/subversion/bindings/cxx/src/private/future_private.hpp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/trunk/subversion/bindings/cxx/tests/test_client_status.cpp
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/tests/test_client_status.cpp?rev=1850774&r1=1850773&r2=1850774&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/tests/test_client_status.cpp 
(original)
+++ subversion/trunk/subversion/bindings/cxx/tests/test_client_status.cpp Tue 
Jan  8 16:55:31 2019
@@ -32,24 +32,40 @@ namespace svn = ::apache::subversion::sv
 BOOST_AUTO_TEST_SUITE(client_status,
                       * boost::unit_test::fixture<init>());
 
+namespace {
+const char working_copy_root[] = "/Users/brane/src/svn/repos/trunk";
+
+const auto status_callback = [](const char* path,
+                                const svn::client::status_notification&)
+                               {
+                                 std::cout << "status on: " << path << 
std::endl;
+                               };
+}
+
 BOOST_AUTO_TEST_CASE(example,
                      * boost::unit_test::disabled())
 {
-  const char working_copy_root[] = "/Users/brane/src/svn/repos/trunk";
-
-  const auto callback = [](const char* path,
-                           const svn::client::status_notification&)
-                          {
-                            std::cout << "status on: " << path << std::endl;
-                          };
   svn::client::context ctx;
-
   const auto revnum = svn::client::status(ctx, working_copy_root,
                                           svn::revision(),
                                           svn::depth::unknown,
                                           svn::client::status_flags::empty,
-                                          callback);
+                                          status_callback);
   std::cout << "got revision: " << long(revnum) << std::endl;
 }
 
+BOOST_AUTO_TEST_CASE(async_example,
+                     * boost::unit_test::disabled())
+{
+  svn::client::context ctx;
+  auto future = svn::client::async::status(ctx, working_copy_root,
+                                           svn::revision(),
+                                           svn::depth::unknown,
+                                           svn::client::status_flags::empty,
+                                           status_callback);
+  BOOST_TEST(future.valid());
+  future.wait();
+  std::cout << "got revision: " << long(future.get()) << std::endl;
+}
+
 BOOST_AUTO_TEST_SUITE_END();


Reply via email to