10ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
20ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// detail/completion_handler.hpp
30ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
50ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
60ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
70ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Distributed under the Boost Software License, Version 1.0. (See accompanying
80ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
90ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#ifndef ASIO_DETAIL_COMPLETION_HANDLER_HPP
120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#define ASIO_DETAIL_COMPLETION_HANDLER_HPP
130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/addressof.hpp"
160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/config.hpp"
170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/fenced_block.hpp"
180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_alloc_helpers.hpp"
190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_invoke_helpers.hpp"
200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/operation.hpp"
210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/push_options.hpp"
230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace asio {
250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace detail {
260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename Handler>
280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieclass completion_handler : public operation
290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiepublic:
310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ASIO_DEFINE_HANDLER_PTR(completion_handler);
320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  completion_handler(Handler& h)
340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : operation(&completion_handler::do_complete),
350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      handler_(ASIO_MOVE_CAST(Handler)(h))
360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  static void do_complete(io_service_impl* owner, operation* base,
400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      const asio::error_code& /*ec*/,
410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t /*bytes_transferred*/)
420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // Take ownership of the handler object.
440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    completion_handler* h(static_cast<completion_handler*>(base));
450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ptr p = { asio::detail::addressof(h->handler_), h, h };
460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ASIO_HANDLER_COMPLETION((h));
480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // Make a copy of the handler so that the memory can be deallocated before
500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // the upcall is made. Even if we're not about to make an upcall, a
510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // sub-object of the handler may be the true owner of the memory associated
520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // with the handler. Consequently, a local copy of the handler is required
530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // to ensure that any owning sub-object remains valid until after we have
540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // deallocated the memory here.
550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    Handler handler(ASIO_MOVE_CAST(Handler)(h->handler_));
560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    p.h = asio::detail::addressof(handler);
570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    p.reset();
580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // Make the upcall if required.
600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    if (owner)
610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      fenced_block b(fenced_block::half);
630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ASIO_HANDLER_INVOCATION_BEGIN(());
640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio_handler_invoke_helpers::invoke(handler, handler);
650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ASIO_HANDLER_INVOCATION_END;
660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieprivate:
700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  Handler handler_;
710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie};
720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace detail
740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace asio
750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/pop_options.hpp"
770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#endif // ASIO_DETAIL_COMPLETION_HANDLER_HPP
79