Home | History | Annotate | Download | only in detail
      1 //
      2 // detail/completion_handler.hpp
      3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      4 //
      5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
      6 //
      7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
      8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
      9 //
     10 
     11 #ifndef ASIO_DETAIL_COMPLETION_HANDLER_HPP
     12 #define ASIO_DETAIL_COMPLETION_HANDLER_HPP
     13 
     14 
     15 #include "asio/detail/addressof.hpp"
     16 #include "asio/detail/config.hpp"
     17 #include "asio/detail/fenced_block.hpp"
     18 #include "asio/detail/handler_alloc_helpers.hpp"
     19 #include "asio/detail/handler_invoke_helpers.hpp"
     20 #include "asio/detail/operation.hpp"
     21 
     22 #include "asio/detail/push_options.hpp"
     23 
     24 namespace asio {
     25 namespace detail {
     26 
     27 template <typename Handler>
     28 class completion_handler : public operation
     29 {
     30 public:
     31   ASIO_DEFINE_HANDLER_PTR(completion_handler);
     32 
     33   completion_handler(Handler& h)
     34     : operation(&completion_handler::do_complete),
     35       handler_(ASIO_MOVE_CAST(Handler)(h))
     36   {
     37   }
     38 
     39   static void do_complete(io_service_impl* owner, operation* base,
     40       const asio::error_code& /*ec*/,
     41       std::size_t /*bytes_transferred*/)
     42   {
     43     // Take ownership of the handler object.
     44     completion_handler* h(static_cast<completion_handler*>(base));
     45     ptr p = { asio::detail::addressof(h->handler_), h, h };
     46 
     47     ASIO_HANDLER_COMPLETION((h));
     48 
     49     // Make a copy of the handler so that the memory can be deallocated before
     50     // the upcall is made. Even if we're not about to make an upcall, a
     51     // sub-object of the handler may be the true owner of the memory associated
     52     // with the handler. Consequently, a local copy of the handler is required
     53     // to ensure that any owning sub-object remains valid until after we have
     54     // deallocated the memory here.
     55     Handler handler(ASIO_MOVE_CAST(Handler)(h->handler_));
     56     p.h = asio::detail::addressof(handler);
     57     p.reset();
     58 
     59     // Make the upcall if required.
     60     if (owner)
     61     {
     62       fenced_block b(fenced_block::half);
     63       ASIO_HANDLER_INVOCATION_BEGIN(());
     64       asio_handler_invoke_helpers::invoke(handler, handler);
     65       ASIO_HANDLER_INVOCATION_END;
     66     }
     67   }
     68 
     69 private:
     70   Handler handler_;
     71 };
     72 
     73 } // namespace detail
     74 } // namespace asio
     75 
     76 #include "asio/detail/pop_options.hpp"
     77 
     78 #endif // ASIO_DETAIL_COMPLETION_HANDLER_HPP
     79