Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:12

0001 //
0002 // system_executor.hpp
0003 // ~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_SYSTEM_EXECUTOR_HPP
0012 #define BOOST_ASIO_SYSTEM_EXECUTOR_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <boost/asio/detail/memory.hpp>
0020 #include <boost/asio/execution.hpp>
0021 
0022 #include <boost/asio/detail/push_options.hpp>
0023 
0024 namespace boost {
0025 namespace asio {
0026 
0027 class system_context;
0028 
0029 /// An executor that uses arbitrary threads.
0030 /**
0031  * The system executor represents an execution context where functions are
0032  * permitted to run on arbitrary threads. When the blocking.never property is
0033  * established, the system executor will schedule the function to run on an
0034  * unspecified system thread pool. When either blocking.possibly or
0035  * blocking.always is established, the executor invokes the function
0036  * immediately.
0037  */
0038 template <typename Blocking, typename Relationship, typename Allocator>
0039 class basic_system_executor
0040 {
0041 public:
0042   /// Default constructor.
0043   basic_system_executor() noexcept
0044     : allocator_(Allocator())
0045   {
0046   }
0047 
0048 #if !defined(GENERATING_DOCUMENTATION)
0049 private:
0050   friend struct boost_asio_require_fn::impl;
0051   friend struct boost_asio_prefer_fn::impl;
0052 #endif // !defined(GENERATING_DOCUMENTATION)
0053 
0054   /// Obtain an executor with the @c blocking.possibly property.
0055   /**
0056    * Do not call this function directly. It is intended for use with the
0057    * boost::asio::require customisation point.
0058    *
0059    * For example:
0060    * @code boost::asio::system_executor ex1;
0061    * auto ex2 = boost::asio::require(ex1,
0062    *     boost::asio::execution::blocking.possibly); @endcode
0063    */
0064   basic_system_executor<execution::blocking_t::possibly_t,
0065       Relationship, Allocator>
0066   require(execution::blocking_t::possibly_t) const
0067   {
0068     return basic_system_executor<execution::blocking_t::possibly_t,
0069         Relationship, Allocator>(allocator_);
0070   }
0071 
0072   /// Obtain an executor with the @c blocking.always property.
0073   /**
0074    * Do not call this function directly. It is intended for use with the
0075    * boost::asio::require customisation point.
0076    *
0077    * For example:
0078    * @code boost::asio::system_executor ex1;
0079    * auto ex2 = boost::asio::require(ex1,
0080    *     boost::asio::execution::blocking.always); @endcode
0081    */
0082   basic_system_executor<execution::blocking_t::always_t,
0083       Relationship, Allocator>
0084   require(execution::blocking_t::always_t) const
0085   {
0086     return basic_system_executor<execution::blocking_t::always_t,
0087         Relationship, Allocator>(allocator_);
0088   }
0089 
0090   /// Obtain an executor with the @c blocking.never property.
0091   /**
0092    * Do not call this function directly. It is intended for use with the
0093    * boost::asio::require customisation point.
0094    *
0095    * For example:
0096    * @code boost::asio::system_executor ex1;
0097    * auto ex2 = boost::asio::require(ex1,
0098    *     boost::asio::execution::blocking.never); @endcode
0099    */
0100   basic_system_executor<execution::blocking_t::never_t,
0101       Relationship, Allocator>
0102   require(execution::blocking_t::never_t) const
0103   {
0104     return basic_system_executor<execution::blocking_t::never_t,
0105         Relationship, Allocator>(allocator_);
0106   }
0107 
0108   /// Obtain an executor with the @c relationship.continuation property.
0109   /**
0110    * Do not call this function directly. It is intended for use with the
0111    * boost::asio::require customisation point.
0112    *
0113    * For example:
0114    * @code boost::asio::system_executor ex1;
0115    * auto ex2 = boost::asio::require(ex1,
0116    *     boost::asio::execution::relationship.continuation); @endcode
0117    */
0118   basic_system_executor<Blocking,
0119       execution::relationship_t::continuation_t, Allocator>
0120   require(execution::relationship_t::continuation_t) const
0121   {
0122     return basic_system_executor<Blocking,
0123         execution::relationship_t::continuation_t, Allocator>(allocator_);
0124   }
0125 
0126   /// Obtain an executor with the @c relationship.fork property.
0127   /**
0128    * Do not call this function directly. It is intended for use with the
0129    * boost::asio::require customisation point.
0130    *
0131    * For example:
0132    * @code boost::asio::system_executor ex1;
0133    * auto ex2 = boost::asio::require(ex1,
0134    *     boost::asio::execution::relationship.fork); @endcode
0135    */
0136   basic_system_executor<Blocking,
0137       execution::relationship_t::fork_t, Allocator>
0138   require(execution::relationship_t::fork_t) const
0139   {
0140     return basic_system_executor<Blocking,
0141         execution::relationship_t::fork_t, Allocator>(allocator_);
0142   }
0143 
0144   /// Obtain an executor with the specified @c allocator property.
0145   /**
0146    * Do not call this function directly. It is intended for use with the
0147    * boost::asio::require customisation point.
0148    *
0149    * For example:
0150    * @code boost::asio::system_executor ex1;
0151    * auto ex2 = boost::asio::require(ex1,
0152    *     boost::asio::execution::allocator(my_allocator)); @endcode
0153    */
0154   template <typename OtherAllocator>
0155   basic_system_executor<Blocking, Relationship, OtherAllocator>
0156   require(execution::allocator_t<OtherAllocator> a) const
0157   {
0158     return basic_system_executor<Blocking,
0159         Relationship, OtherAllocator>(a.value());
0160   }
0161 
0162   /// Obtain an executor with the default @c allocator property.
0163   /**
0164    * Do not call this function directly. It is intended for use with the
0165    * boost::asio::require customisation point.
0166    *
0167    * For example:
0168    * @code boost::asio::system_executor ex1;
0169    * auto ex2 = boost::asio::require(ex1,
0170    *     boost::asio::execution::allocator); @endcode
0171    */
0172   basic_system_executor<Blocking, Relationship, std::allocator<void>>
0173   require(execution::allocator_t<void>) const
0174   {
0175     return basic_system_executor<Blocking,
0176         Relationship, std::allocator<void>>();
0177   }
0178 
0179 #if !defined(GENERATING_DOCUMENTATION)
0180 private:
0181   friend struct boost_asio_query_fn::impl;
0182   friend struct boost::asio::execution::detail::blocking_t<0>;
0183   friend struct boost::asio::execution::detail::mapping_t<0>;
0184   friend struct boost::asio::execution::detail::outstanding_work_t<0>;
0185   friend struct boost::asio::execution::detail::relationship_t<0>;
0186 #endif // !defined(GENERATING_DOCUMENTATION)
0187 
0188   /// Query the current value of the @c mapping property.
0189   /**
0190    * Do not call this function directly. It is intended for use with the
0191    * boost::asio::query customisation point.
0192    *
0193    * For example:
0194    * @code boost::asio::system_executor ex;
0195    * if (boost::asio::query(ex, boost::asio::execution::mapping)
0196    *       == boost::asio::execution::mapping.thread)
0197    *   ... @endcode
0198    */
0199   static constexpr execution::mapping_t query(
0200       execution::mapping_t) noexcept
0201   {
0202     return execution::mapping.thread;
0203   }
0204 
0205   /// Query the current value of the @c context property.
0206   /**
0207    * Do not call this function directly. It is intended for use with the
0208    * boost::asio::query customisation point.
0209    *
0210    * For example:
0211    * @code boost::asio::system_executor ex;
0212    * boost::asio::system_context& pool = boost::asio::query(
0213    *     ex, boost::asio::execution::context); @endcode
0214    */
0215   static system_context& query(execution::context_t) noexcept;
0216 
0217   /// Query the current value of the @c blocking property.
0218   /**
0219    * Do not call this function directly. It is intended for use with the
0220    * boost::asio::query customisation point.
0221    *
0222    * For example:
0223    * @code boost::asio::system_executor ex;
0224    * if (boost::asio::query(ex, boost::asio::execution::blocking)
0225    *       == boost::asio::execution::blocking.always)
0226    *   ... @endcode
0227    */
0228   static constexpr execution::blocking_t query(
0229       execution::blocking_t) noexcept
0230   {
0231     return Blocking();
0232   }
0233 
0234   /// Query the current value of the @c relationship property.
0235   /**
0236    * Do not call this function directly. It is intended for use with the
0237    * boost::asio::query customisation point.
0238    *
0239    * For example:
0240    * @code boost::asio::system_executor ex;
0241    * if (boost::asio::query(ex, boost::asio::execution::relationship)
0242    *       == boost::asio::execution::relationship.continuation)
0243    *   ... @endcode
0244    */
0245   static constexpr execution::relationship_t query(
0246       execution::relationship_t) noexcept
0247   {
0248     return Relationship();
0249   }
0250 
0251   /// Query the current value of the @c allocator property.
0252   /**
0253    * Do not call this function directly. It is intended for use with the
0254    * boost::asio::query customisation point.
0255    *
0256    * For example:
0257    * @code boost::asio::system_executor ex;
0258    * auto alloc = boost::asio::query(ex,
0259    *     boost::asio::execution::allocator); @endcode
0260    */
0261   template <typename OtherAllocator>
0262   constexpr Allocator query(
0263       execution::allocator_t<OtherAllocator>) const noexcept
0264   {
0265     return allocator_;
0266   }
0267 
0268   /// Query the current value of the @c allocator property.
0269   /**
0270    * Do not call this function directly. It is intended for use with the
0271    * boost::asio::query customisation point.
0272    *
0273    * For example:
0274    * @code boost::asio::system_executor ex;
0275    * auto alloc = boost::asio::query(ex,
0276    *     boost::asio::execution::allocator); @endcode
0277    */
0278   constexpr Allocator query(
0279       execution::allocator_t<void>) const noexcept
0280   {
0281     return allocator_;
0282   }
0283 
0284   /// Query the occupancy (recommended number of work items) for the system
0285   /// context.
0286   /**
0287    * Do not call this function directly. It is intended for use with the
0288    * boost::asio::query customisation point.
0289    *
0290    * For example:
0291    * @code boost::asio::system_executor ex;
0292    * std::size_t occupancy = boost::asio::query(
0293    *     ex, boost::asio::execution::occupancy); @endcode
0294    */
0295   std::size_t query(execution::occupancy_t) const noexcept;
0296 
0297 public:
0298   /// Compare two executors for equality.
0299   /**
0300    * Two executors are equal if they refer to the same underlying io_context.
0301    */
0302   friend bool operator==(const basic_system_executor&,
0303       const basic_system_executor&) noexcept
0304   {
0305     return true;
0306   }
0307 
0308   /// Compare two executors for inequality.
0309   /**
0310    * Two executors are equal if they refer to the same underlying io_context.
0311    */
0312   friend bool operator!=(const basic_system_executor&,
0313       const basic_system_executor&) noexcept
0314   {
0315     return false;
0316   }
0317 
0318   /// Execution function.
0319   template <typename Function>
0320   void execute(Function&& f) const
0321   {
0322     this->do_execute(static_cast<Function&&>(f), Blocking());
0323   }
0324 
0325 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0326 public:
0327   /// Obtain the underlying execution context.
0328   system_context& context() const noexcept;
0329 
0330   /// Inform the executor that it has some outstanding work to do.
0331   /**
0332    * For the system executor, this is a no-op.
0333    */
0334   void on_work_started() const noexcept
0335   {
0336   }
0337 
0338   /// Inform the executor that some work is no longer outstanding.
0339   /**
0340    * For the system executor, this is a no-op.
0341    */
0342   void on_work_finished() const noexcept
0343   {
0344   }
0345 
0346   /// Request the system executor to invoke the given function object.
0347   /**
0348    * This function is used to ask the executor to execute the given function
0349    * object. The function object will always be executed inside this function.
0350    *
0351    * @param f The function object to be called. The executor will make
0352    * a copy of the handler object as required. The function signature of the
0353    * function object must be: @code void function(); @endcode
0354    *
0355    * @param a An allocator that may be used by the executor to allocate the
0356    * internal storage needed for function invocation.
0357    */
0358   template <typename Function, typename OtherAllocator>
0359   void dispatch(Function&& f, const OtherAllocator& a) const;
0360 
0361   /// Request the system executor to invoke the given function object.
0362   /**
0363    * This function is used to ask the executor to execute the given function
0364    * object. The function object will never be executed inside this function.
0365    * Instead, it will be scheduled to run on an unspecified system thread pool.
0366    *
0367    * @param f The function object to be called. The executor will make
0368    * a copy of the handler object as required. The function signature of the
0369    * function object must be: @code void function(); @endcode
0370    *
0371    * @param a An allocator that may be used by the executor to allocate the
0372    * internal storage needed for function invocation.
0373    */
0374   template <typename Function, typename OtherAllocator>
0375   void post(Function&& f, const OtherAllocator& a) const;
0376 
0377   /// Request the system executor to invoke the given function object.
0378   /**
0379    * This function is used to ask the executor to execute the given function
0380    * object. The function object will never be executed inside this function.
0381    * Instead, it will be scheduled to run on an unspecified system thread pool.
0382    *
0383    * @param f The function object to be called. The executor will make
0384    * a copy of the handler object as required. The function signature of the
0385    * function object must be: @code void function(); @endcode
0386    *
0387    * @param a An allocator that may be used by the executor to allocate the
0388    * internal storage needed for function invocation.
0389    */
0390   template <typename Function, typename OtherAllocator>
0391   void defer(Function&& f, const OtherAllocator& a) const;
0392 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0393 
0394 private:
0395   template <typename, typename, typename> friend class basic_system_executor;
0396 
0397   // Constructor used by require().
0398   basic_system_executor(const Allocator& a)
0399     : allocator_(a)
0400   {
0401   }
0402 
0403   /// Execution helper implementation for the possibly blocking property.
0404   template <typename Function>
0405   void do_execute(Function&& f,
0406       execution::blocking_t::possibly_t) const;
0407 
0408   /// Execution helper implementation for the always blocking property.
0409   template <typename Function>
0410   void do_execute(Function&& f,
0411       execution::blocking_t::always_t) const;
0412 
0413   /// Execution helper implementation for the never blocking property.
0414   template <typename Function>
0415   void do_execute(Function&& f,
0416       execution::blocking_t::never_t) const;
0417 
0418   // The allocator used for execution functions.
0419   Allocator allocator_;
0420 };
0421 
0422 /// An executor that uses arbitrary threads.
0423 /**
0424  * The system executor represents an execution context where functions are
0425  * permitted to run on arbitrary threads. When the blocking.never property is
0426  * established, the system executor will schedule the function to run on an
0427  * unspecified system thread pool. When either blocking.possibly or
0428  * blocking.always is established, the executor invokes the function
0429  * immediately.
0430  */
0431 typedef basic_system_executor<execution::blocking_t::possibly_t,
0432     execution::relationship_t::fork_t, std::allocator<void>>
0433   system_executor;
0434 
0435 #if !defined(GENERATING_DOCUMENTATION)
0436 
0437 namespace traits {
0438 
0439 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
0440 
0441 template <typename Blocking, typename Relationship, typename Allocator>
0442 struct equality_comparable<
0443     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>
0444   >
0445 {
0446   static constexpr bool is_valid = true;
0447   static constexpr bool is_noexcept = true;
0448 };
0449 
0450 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
0451 
0452 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
0453 
0454 template <typename Blocking, typename Relationship,
0455     typename Allocator, typename Function>
0456 struct execute_member<
0457     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0458     Function
0459   >
0460 {
0461   static constexpr bool is_valid = true;
0462   static constexpr bool is_noexcept = false;
0463   typedef void result_type;
0464 };
0465 
0466 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
0467 
0468 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
0469 
0470 template <typename Blocking, typename Relationship, typename Allocator>
0471 struct require_member<
0472     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0473     boost::asio::execution::blocking_t::possibly_t
0474   >
0475 {
0476   static constexpr bool is_valid = true;
0477   static constexpr bool is_noexcept = false;
0478   typedef boost::asio::basic_system_executor<
0479       boost::asio::execution::blocking_t::possibly_t,
0480       Relationship, Allocator> result_type;
0481 };
0482 
0483 template <typename Blocking, typename Relationship, typename Allocator>
0484 struct require_member<
0485     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0486     boost::asio::execution::blocking_t::always_t
0487   >
0488 {
0489   static constexpr bool is_valid = true;
0490   static constexpr bool is_noexcept = false;
0491   typedef boost::asio::basic_system_executor<
0492       boost::asio::execution::blocking_t::always_t,
0493       Relationship, Allocator> result_type;
0494 };
0495 
0496 template <typename Blocking, typename Relationship, typename Allocator>
0497 struct require_member<
0498     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0499     boost::asio::execution::blocking_t::never_t
0500   >
0501 {
0502   static constexpr bool is_valid = true;
0503   static constexpr bool is_noexcept = false;
0504   typedef boost::asio::basic_system_executor<
0505       boost::asio::execution::blocking_t::never_t,
0506       Relationship, Allocator> result_type;
0507 };
0508 
0509 template <typename Blocking, typename Relationship, typename Allocator>
0510 struct require_member<
0511     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0512     boost::asio::execution::relationship_t::fork_t
0513   >
0514 {
0515   static constexpr bool is_valid = true;
0516   static constexpr bool is_noexcept = false;
0517   typedef boost::asio::basic_system_executor<Blocking,
0518       boost::asio::execution::relationship_t::fork_t,
0519       Allocator> result_type;
0520 };
0521 
0522 template <typename Blocking, typename Relationship, typename Allocator>
0523 struct require_member<
0524     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0525     boost::asio::execution::relationship_t::continuation_t
0526   >
0527 {
0528   static constexpr bool is_valid = true;
0529   static constexpr bool is_noexcept = false;
0530   typedef boost::asio::basic_system_executor<Blocking,
0531       boost::asio::execution::relationship_t::continuation_t,
0532       Allocator> result_type;
0533 };
0534 
0535 template <typename Blocking, typename Relationship, typename Allocator>
0536 struct require_member<
0537     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0538     boost::asio::execution::allocator_t<void>
0539   >
0540 {
0541   static constexpr bool is_valid = true;
0542   static constexpr bool is_noexcept = false;
0543   typedef boost::asio::basic_system_executor<Blocking,
0544       Relationship, std::allocator<void>> result_type;
0545 };
0546 
0547 template <typename Blocking, typename Relationship,
0548     typename Allocator, typename OtherAllocator>
0549 struct require_member<
0550     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0551     boost::asio::execution::allocator_t<OtherAllocator>
0552   >
0553 {
0554   static constexpr bool is_valid = true;
0555   static constexpr bool is_noexcept = false;
0556   typedef boost::asio::basic_system_executor<Blocking,
0557       Relationship, OtherAllocator> result_type;
0558 };
0559 
0560 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
0561 
0562 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
0563 
0564 template <typename Blocking, typename Relationship,
0565     typename Allocator, typename Property>
0566 struct query_static_constexpr_member<
0567     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0568     Property,
0569     typename boost::asio::enable_if<
0570       boost::asio::is_convertible<
0571         Property,
0572         boost::asio::execution::mapping_t
0573       >::value
0574     >::type
0575   >
0576 {
0577   static constexpr bool is_valid = true;
0578   static constexpr bool is_noexcept = true;
0579   typedef boost::asio::execution::mapping_t::thread_t result_type;
0580 
0581   static constexpr result_type value() noexcept
0582   {
0583     return result_type();
0584   }
0585 };
0586 
0587 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
0588 
0589 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
0590 
0591 template <typename Blocking, typename Relationship,
0592     typename Allocator, typename Property>
0593 struct query_member<
0594     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0595     Property,
0596     typename boost::asio::enable_if<
0597       boost::asio::is_convertible<
0598         Property,
0599         boost::asio::execution::blocking_t
0600       >::value
0601     >::type
0602   >
0603 {
0604   static constexpr bool is_valid = true;
0605   static constexpr bool is_noexcept = true;
0606   typedef boost::asio::execution::blocking_t result_type;
0607 };
0608 
0609 template <typename Blocking, typename Relationship,
0610     typename Allocator, typename Property>
0611 struct query_member<
0612     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0613     Property,
0614     typename boost::asio::enable_if<
0615       boost::asio::is_convertible<
0616         Property,
0617         boost::asio::execution::relationship_t
0618       >::value
0619     >::type
0620   >
0621 {
0622   static constexpr bool is_valid = true;
0623   static constexpr bool is_noexcept = true;
0624   typedef boost::asio::execution::relationship_t result_type;
0625 };
0626 
0627 template <typename Blocking, typename Relationship, typename Allocator>
0628 struct query_member<
0629     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0630     boost::asio::execution::context_t
0631   >
0632 {
0633   static constexpr bool is_valid = true;
0634   static constexpr bool is_noexcept = true;
0635   typedef boost::asio::system_context& result_type;
0636 };
0637 
0638 template <typename Blocking, typename Relationship, typename Allocator>
0639 struct query_member<
0640     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0641     boost::asio::execution::allocator_t<void>
0642   >
0643 {
0644   static constexpr bool is_valid = true;
0645   static constexpr bool is_noexcept = true;
0646   typedef Allocator result_type;
0647 };
0648 
0649 template <typename Blocking, typename Relationship, typename Allocator>
0650 struct query_member<
0651     boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
0652     boost::asio::execution::allocator_t<Allocator>
0653   >
0654 {
0655   static constexpr bool is_valid = true;
0656   static constexpr bool is_noexcept = true;
0657   typedef Allocator result_type;
0658 };
0659 
0660 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
0661 
0662 } // namespace traits
0663 
0664 #endif // !defined(GENERATING_DOCUMENTATION)
0665 
0666 } // namespace asio
0667 } // namespace boost
0668 
0669 #include <boost/asio/detail/pop_options.hpp>
0670 
0671 #include <boost/asio/impl/system_executor.hpp>
0672 
0673 #endif // BOOST_ASIO_SYSTEM_EXECUTOR_HPP