1 // 2 // detail/executor_op.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 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 BOOST_ASIO_DETAIL_EXECUTOR_OP_HPP 12 #define BOOST_ASIO_DETAIL_EXECUTOR_OP_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 #include <boost/asio/detail/fenced_block.hpp> 20 #include <boost/asio/detail/handler_alloc_helpers.hpp> 21 #include <boost/asio/detail/handler_invoke_helpers.hpp> 22 #include <boost/asio/detail/scheduler_operation.hpp> 23 24 #include <boost/asio/detail/push_options.hpp> 25 26 namespace boost { 27 namespace asio { 28 namespace detail { 29 30 template <typename Handler, typename Alloc, 31 typename Operation = scheduler_operation> 32 class executor_op : public Operation 33 { 34 public: 35 BOOST_ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(executor_op); 36 37 template <typename H> executor_op(BOOST_ASIO_MOVE_ARG (H)h,const Alloc & allocator)38 executor_op(BOOST_ASIO_MOVE_ARG(H) h, const Alloc& allocator) 39 : Operation(&executor_op::do_complete), 40 handler_(BOOST_ASIO_MOVE_CAST(H)(h)), 41 allocator_(allocator) 42 { 43 } 44 do_complete(void * owner,Operation * base,const boost::system::error_code &,std::size_t)45 static void do_complete(void* owner, Operation* base, 46 const boost::system::error_code& /*ec*/, 47 std::size_t /*bytes_transferred*/) 48 { 49 // Take ownership of the handler object. 50 executor_op* o(static_cast<executor_op*>(base)); 51 Alloc allocator(o->allocator_); 52 ptr p = { detail::addressof(allocator), o, o }; 53 54 BOOST_ASIO_HANDLER_COMPLETION((*o)); 55 56 // Make a copy of the handler so that the memory can be deallocated before 57 // the upcall is made. Even if we're not about to make an upcall, a 58 // sub-object of the handler may be the true owner of the memory associated 59 // with the handler. Consequently, a local copy of the handler is required 60 // to ensure that any owning sub-object remains valid until after we have 61 // deallocated the memory here. 62 Handler handler(BOOST_ASIO_MOVE_CAST(Handler)(o->handler_)); 63 p.reset(); 64 65 // Make the upcall if required. 66 if (owner) 67 { 68 fenced_block b(fenced_block::half); 69 BOOST_ASIO_HANDLER_INVOCATION_BEGIN(()); 70 boost_asio_handler_invoke_helpers::invoke(handler, handler); 71 BOOST_ASIO_HANDLER_INVOCATION_END; 72 } 73 } 74 75 private: 76 Handler handler_; 77 Alloc allocator_; 78 }; 79 80 } // namespace detail 81 } // namespace asio 82 } // namespace boost 83 84 #include <boost/asio/detail/pop_options.hpp> 85 86 #endif // BOOST_ASIO_DETAIL_EXECUTOR_OP_HPP 87