File indexing completed on 2025-09-18 08:35:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_THREAD_POOL_HPP
0012 #define BOOST_ASIO_THREAD_POOL_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019 #include <boost/asio/detail/atomic_count.hpp>
0020 #include <boost/asio/detail/scheduler.hpp>
0021 #include <boost/asio/detail/thread_group.hpp>
0022 #include <boost/asio/execution.hpp>
0023 #include <boost/asio/execution_context.hpp>
0024
0025 #include <boost/asio/detail/push_options.hpp>
0026
0027 namespace boost {
0028 namespace asio {
0029 namespace detail {
0030 struct thread_pool_bits
0031 {
0032 static constexpr unsigned int blocking_never = 1;
0033 static constexpr unsigned int blocking_always = 2;
0034 static constexpr unsigned int blocking_mask = 3;
0035 static constexpr unsigned int relationship_continuation = 4;
0036 static constexpr unsigned int outstanding_work_tracked = 8;
0037 };
0038 }
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 class thread_pool
0087 : public execution_context
0088 {
0089 public:
0090 template <typename Allocator, unsigned int Bits>
0091 class basic_executor_type;
0092
0093 template <typename Allocator, unsigned int Bits>
0094 friend class basic_executor_type;
0095
0096
0097 typedef basic_executor_type<std::allocator<void>, 0> executor_type;
0098
0099 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0100
0101 BOOST_ASIO_DECL thread_pool();
0102 #endif
0103
0104
0105 BOOST_ASIO_DECL thread_pool(std::size_t num_threads);
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 BOOST_ASIO_DECL thread_pool(std::size_t num_threads,
0118 const execution_context::service_maker& initial_services);
0119
0120
0121
0122
0123
0124 BOOST_ASIO_DECL ~thread_pool();
0125
0126
0127 executor_type get_executor() noexcept;
0128
0129
0130 executor_type executor() noexcept;
0131
0132
0133
0134
0135
0136
0137 BOOST_ASIO_DECL void stop();
0138
0139
0140
0141
0142
0143
0144
0145 BOOST_ASIO_DECL void attach();
0146
0147
0148
0149
0150
0151
0152
0153 BOOST_ASIO_DECL void join();
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163 BOOST_ASIO_DECL void wait();
0164
0165 private:
0166 thread_pool(const thread_pool&) = delete;
0167 thread_pool& operator=(const thread_pool&) = delete;
0168
0169 struct thread_function;
0170
0171
0172 BOOST_ASIO_DECL detail::scheduler& add_scheduler(detail::scheduler* s);
0173
0174
0175 detail::scheduler& scheduler_;
0176
0177
0178 detail::thread_group threads_;
0179
0180
0181 detail::atomic_count num_threads_;
0182
0183
0184 bool joinable_;
0185 };
0186
0187
0188 template <typename Allocator, unsigned int Bits>
0189 class thread_pool::basic_executor_type : detail::thread_pool_bits
0190 {
0191 public:
0192
0193 basic_executor_type(const basic_executor_type& other) noexcept
0194 : pool_(other.pool_),
0195 allocator_(other.allocator_),
0196 bits_(other.bits_)
0197 {
0198 if (Bits & outstanding_work_tracked)
0199 if (pool_)
0200 pool_->scheduler_.work_started();
0201 }
0202
0203
0204 basic_executor_type(basic_executor_type&& other) noexcept
0205 : pool_(other.pool_),
0206 allocator_(static_cast<Allocator&&>(other.allocator_)),
0207 bits_(other.bits_)
0208 {
0209 if (Bits & outstanding_work_tracked)
0210 other.pool_ = 0;
0211 }
0212
0213
0214 ~basic_executor_type() noexcept
0215 {
0216 if (Bits & outstanding_work_tracked)
0217 if (pool_)
0218 pool_->scheduler_.work_finished();
0219 }
0220
0221
0222 basic_executor_type& operator=(const basic_executor_type& other) noexcept;
0223
0224
0225 basic_executor_type& operator=(basic_executor_type&& other) noexcept;
0226
0227 #if !defined(GENERATING_DOCUMENTATION)
0228 private:
0229 friend struct boost_asio_require_fn::impl;
0230 friend struct boost_asio_prefer_fn::impl;
0231 #endif
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 constexpr basic_executor_type<Allocator,
0244 BOOST_ASIO_UNSPECIFIED(Bits & ~blocking_mask)>
0245 require(execution::blocking_t::possibly_t) const
0246 {
0247 return basic_executor_type<Allocator, Bits & ~blocking_mask>(
0248 pool_, allocator_, bits_ & ~blocking_mask);
0249 }
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261 constexpr basic_executor_type<Allocator,
0262 BOOST_ASIO_UNSPECIFIED((Bits & ~blocking_mask) | blocking_always)>
0263 require(execution::blocking_t::always_t) const
0264 {
0265 return basic_executor_type<Allocator,
0266 BOOST_ASIO_UNSPECIFIED((Bits & ~blocking_mask) | blocking_always)>(
0267 pool_, allocator_, bits_ & ~blocking_mask);
0268 }
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280 constexpr basic_executor_type<Allocator,
0281 BOOST_ASIO_UNSPECIFIED(Bits & ~blocking_mask)>
0282 require(execution::blocking_t::never_t) const
0283 {
0284 return basic_executor_type<Allocator, Bits & ~blocking_mask>(
0285 pool_, allocator_, (bits_ & ~blocking_mask) | blocking_never);
0286 }
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298 constexpr basic_executor_type require(execution::relationship_t::fork_t) const
0299 {
0300 return basic_executor_type(pool_,
0301 allocator_, bits_ & ~relationship_continuation);
0302 }
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314 constexpr basic_executor_type require(
0315 execution::relationship_t::continuation_t) const
0316 {
0317 return basic_executor_type(pool_,
0318 allocator_, bits_ | relationship_continuation);
0319 }
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331 constexpr basic_executor_type<Allocator,
0332 BOOST_ASIO_UNSPECIFIED(Bits | outstanding_work_tracked)>
0333 require(execution::outstanding_work_t::tracked_t) const
0334 {
0335 return basic_executor_type<Allocator, Bits | outstanding_work_tracked>(
0336 pool_, allocator_, bits_);
0337 }
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349 constexpr basic_executor_type<Allocator,
0350 BOOST_ASIO_UNSPECIFIED(Bits & ~outstanding_work_tracked)>
0351 require(execution::outstanding_work_t::untracked_t) const
0352 {
0353 return basic_executor_type<Allocator, Bits & ~outstanding_work_tracked>(
0354 pool_, allocator_, bits_);
0355 }
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367 template <typename OtherAllocator>
0368 constexpr basic_executor_type<OtherAllocator, Bits>
0369 require(execution::allocator_t<OtherAllocator> a) const
0370 {
0371 return basic_executor_type<OtherAllocator, Bits>(
0372 pool_, a.value(), bits_);
0373 }
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385 constexpr basic_executor_type<std::allocator<void>, Bits>
0386 require(execution::allocator_t<void>) const
0387 {
0388 return basic_executor_type<std::allocator<void>, Bits>(
0389 pool_, std::allocator<void>(), bits_);
0390 }
0391
0392 #if !defined(GENERATING_DOCUMENTATION)
0393 private:
0394 friend struct boost_asio_query_fn::impl;
0395 friend struct boost::asio::execution::detail::mapping_t<0>;
0396 friend struct boost::asio::execution::detail::outstanding_work_t<0>;
0397 #endif
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410 static constexpr execution::mapping_t query(execution::mapping_t) noexcept
0411 {
0412 return execution::mapping.thread;
0413 }
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425 thread_pool& query(execution::context_t) const noexcept
0426 {
0427 return *pool_;
0428 }
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441 constexpr execution::blocking_t query(execution::blocking_t) const noexcept
0442 {
0443 return (bits_ & blocking_never)
0444 ? execution::blocking_t(execution::blocking.never)
0445 : ((Bits & blocking_always)
0446 ? execution::blocking_t(execution::blocking.always)
0447 : execution::blocking_t(execution::blocking.possibly));
0448 }
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461 constexpr execution::relationship_t query(
0462 execution::relationship_t) const noexcept
0463 {
0464 return (bits_ & relationship_continuation)
0465 ? execution::relationship_t(execution::relationship.continuation)
0466 : execution::relationship_t(execution::relationship.fork);
0467 }
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480 static constexpr execution::outstanding_work_t query(
0481 execution::outstanding_work_t) noexcept
0482 {
0483 return (Bits & outstanding_work_tracked)
0484 ? execution::outstanding_work_t(execution::outstanding_work.tracked)
0485 : execution::outstanding_work_t(execution::outstanding_work.untracked);
0486 }
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498 template <typename OtherAllocator>
0499 constexpr Allocator query(
0500 execution::allocator_t<OtherAllocator>) const noexcept
0501 {
0502 return allocator_;
0503 }
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515 constexpr Allocator query(execution::allocator_t<void>) const noexcept
0516 {
0517 return allocator_;
0518 }
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530 std::size_t query(execution::occupancy_t) const noexcept
0531 {
0532 return static_cast<std::size_t>(pool_->num_threads_);
0533 }
0534
0535 public:
0536
0537
0538
0539
0540
0541 bool running_in_this_thread() const noexcept;
0542
0543
0544
0545
0546
0547 friend bool operator==(const basic_executor_type& a,
0548 const basic_executor_type& b) noexcept
0549 {
0550 return a.pool_ == b.pool_
0551 && a.allocator_ == b.allocator_
0552 && a.bits_ == b.bits_;
0553 }
0554
0555
0556
0557
0558
0559 friend bool operator!=(const basic_executor_type& a,
0560 const basic_executor_type& b) noexcept
0561 {
0562 return a.pool_ != b.pool_
0563 || a.allocator_ != b.allocator_
0564 || a.bits_ != b.bits_;
0565 }
0566
0567
0568 template <typename Function>
0569 void execute(Function&& f) const
0570 {
0571 this->do_execute(static_cast<Function&&>(f),
0572 integral_constant<bool, (Bits & blocking_always) != 0>());
0573 }
0574
0575 public:
0576 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0577
0578 thread_pool& context() const noexcept;
0579
0580
0581
0582
0583
0584
0585
0586 void on_work_started() const noexcept;
0587
0588
0589
0590
0591
0592
0593
0594 void on_work_finished() const noexcept;
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610 template <typename Function, typename OtherAllocator>
0611 void dispatch(Function&& f, const OtherAllocator& a) const;
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626 template <typename Function, typename OtherAllocator>
0627 void post(Function&& f, const OtherAllocator& a) const;
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646 template <typename Function, typename OtherAllocator>
0647 void defer(Function&& f, const OtherAllocator& a) const;
0648 #endif
0649
0650 private:
0651 friend class thread_pool;
0652 template <typename, unsigned int> friend class basic_executor_type;
0653
0654
0655 explicit basic_executor_type(thread_pool& p) noexcept
0656 : pool_(&p),
0657 allocator_(),
0658 bits_(0)
0659 {
0660 if (Bits & outstanding_work_tracked)
0661 pool_->scheduler_.work_started();
0662 }
0663
0664
0665 basic_executor_type(thread_pool* p,
0666 const Allocator& a, unsigned int bits) noexcept
0667 : pool_(p),
0668 allocator_(a),
0669 bits_(bits)
0670 {
0671 if (Bits & outstanding_work_tracked)
0672 if (pool_)
0673 pool_->scheduler_.work_started();
0674 }
0675
0676
0677 template <typename Function>
0678 void do_execute(Function&& f, false_type) const;
0679
0680
0681 template <typename Function>
0682 void do_execute(Function&& f, true_type) const;
0683
0684
0685 thread_pool* pool_;
0686
0687
0688 Allocator allocator_;
0689
0690
0691 unsigned int bits_;
0692 };
0693
0694 #if !defined(GENERATING_DOCUMENTATION)
0695
0696 namespace traits {
0697
0698 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
0699
0700 template <typename Allocator, unsigned int Bits>
0701 struct equality_comparable<
0702 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>
0703 >
0704 {
0705 static constexpr bool is_valid = true;
0706 static constexpr bool is_noexcept = true;
0707 };
0708
0709 #endif
0710
0711 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
0712
0713 template <typename Allocator, unsigned int Bits, typename Function>
0714 struct execute_member<
0715 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0716 Function
0717 >
0718 {
0719 static constexpr bool is_valid = true;
0720 static constexpr bool is_noexcept = false;
0721 typedef void result_type;
0722 };
0723
0724 #endif
0725
0726 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
0727
0728 template <typename Allocator, unsigned int Bits>
0729 struct require_member<
0730 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0731 boost::asio::execution::blocking_t::possibly_t
0732 > : boost::asio::detail::thread_pool_bits
0733 {
0734 static constexpr bool is_valid = true;
0735 static constexpr bool is_noexcept = true;
0736 typedef boost::asio::thread_pool::basic_executor_type<
0737 Allocator, Bits & ~blocking_mask> result_type;
0738 };
0739
0740 template <typename Allocator, unsigned int Bits>
0741 struct require_member<
0742 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0743 boost::asio::execution::blocking_t::always_t
0744 > : boost::asio::detail::thread_pool_bits
0745 {
0746 static constexpr bool is_valid = true;
0747 static constexpr bool is_noexcept = false;
0748 typedef boost::asio::thread_pool::basic_executor_type<Allocator,
0749 (Bits & ~blocking_mask) | blocking_always> result_type;
0750 };
0751
0752 template <typename Allocator, unsigned int Bits>
0753 struct require_member<
0754 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0755 boost::asio::execution::blocking_t::never_t
0756 > : boost::asio::detail::thread_pool_bits
0757 {
0758 static constexpr bool is_valid = true;
0759 static constexpr bool is_noexcept = false;
0760 typedef boost::asio::thread_pool::basic_executor_type<
0761 Allocator, Bits & ~blocking_mask> result_type;
0762 };
0763
0764 template <typename Allocator, unsigned int Bits>
0765 struct require_member<
0766 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0767 boost::asio::execution::relationship_t::fork_t
0768 >
0769 {
0770 static constexpr bool is_valid = true;
0771 static constexpr bool is_noexcept = false;
0772 typedef boost::asio::thread_pool::basic_executor_type<
0773 Allocator, Bits> result_type;
0774 };
0775
0776 template <typename Allocator, unsigned int Bits>
0777 struct require_member<
0778 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0779 boost::asio::execution::relationship_t::continuation_t
0780 >
0781 {
0782 static constexpr bool is_valid = true;
0783 static constexpr bool is_noexcept = false;
0784 typedef boost::asio::thread_pool::basic_executor_type<
0785 Allocator, Bits> result_type;
0786 };
0787
0788 template <typename Allocator, unsigned int Bits>
0789 struct require_member<
0790 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0791 boost::asio::execution::outstanding_work_t::tracked_t
0792 > : boost::asio::detail::thread_pool_bits
0793 {
0794 static constexpr bool is_valid = true;
0795 static constexpr bool is_noexcept = false;
0796 typedef boost::asio::thread_pool::basic_executor_type<
0797 Allocator, Bits | outstanding_work_tracked> result_type;
0798 };
0799
0800 template <typename Allocator, unsigned int Bits>
0801 struct require_member<
0802 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0803 boost::asio::execution::outstanding_work_t::untracked_t
0804 > : boost::asio::detail::thread_pool_bits
0805 {
0806 static constexpr bool is_valid = true;
0807 static constexpr bool is_noexcept = false;
0808 typedef boost::asio::thread_pool::basic_executor_type<
0809 Allocator, Bits & ~outstanding_work_tracked> result_type;
0810 };
0811
0812 template <typename Allocator, unsigned int Bits>
0813 struct require_member<
0814 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0815 boost::asio::execution::allocator_t<void>
0816 >
0817 {
0818 static constexpr bool is_valid = true;
0819 static constexpr bool is_noexcept = false;
0820 typedef boost::asio::thread_pool::basic_executor_type<
0821 std::allocator<void>, Bits> result_type;
0822 };
0823
0824 template <unsigned int Bits,
0825 typename Allocator, typename OtherAllocator>
0826 struct require_member<
0827 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0828 boost::asio::execution::allocator_t<OtherAllocator>
0829 >
0830 {
0831 static constexpr bool is_valid = true;
0832 static constexpr bool is_noexcept = false;
0833 typedef boost::asio::thread_pool::basic_executor_type<
0834 OtherAllocator, Bits> result_type;
0835 };
0836
0837 #endif
0838
0839 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
0840
0841 template <typename Allocator, unsigned int Bits, typename Property>
0842 struct query_static_constexpr_member<
0843 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0844 Property,
0845 typename boost::asio::enable_if<
0846 boost::asio::is_convertible<
0847 Property,
0848 boost::asio::execution::outstanding_work_t
0849 >::value
0850 >::type
0851 > : boost::asio::detail::thread_pool_bits
0852 {
0853 static constexpr bool is_valid = true;
0854 static constexpr bool is_noexcept = true;
0855 typedef boost::asio::execution::outstanding_work_t result_type;
0856
0857 static constexpr result_type value() noexcept
0858 {
0859 return (Bits & outstanding_work_tracked)
0860 ? execution::outstanding_work_t(execution::outstanding_work.tracked)
0861 : execution::outstanding_work_t(execution::outstanding_work.untracked);
0862 }
0863 };
0864
0865 template <typename Allocator, unsigned int Bits, typename Property>
0866 struct query_static_constexpr_member<
0867 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0868 Property,
0869 typename boost::asio::enable_if<
0870 boost::asio::is_convertible<
0871 Property,
0872 boost::asio::execution::mapping_t
0873 >::value
0874 >::type
0875 >
0876 {
0877 static constexpr bool is_valid = true;
0878 static constexpr bool is_noexcept = true;
0879 typedef boost::asio::execution::mapping_t::thread_t result_type;
0880
0881 static constexpr result_type value() noexcept
0882 {
0883 return result_type();
0884 }
0885 };
0886
0887 #endif
0888
0889 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
0890
0891 template <typename Allocator, unsigned int Bits, typename Property>
0892 struct query_member<
0893 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0894 Property,
0895 typename boost::asio::enable_if<
0896 boost::asio::is_convertible<
0897 Property,
0898 boost::asio::execution::blocking_t
0899 >::value
0900 >::type
0901 >
0902 {
0903 static constexpr bool is_valid = true;
0904 static constexpr bool is_noexcept = true;
0905 typedef boost::asio::execution::blocking_t result_type;
0906 };
0907
0908 template <typename Allocator, unsigned int Bits, typename Property>
0909 struct query_member<
0910 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0911 Property,
0912 typename boost::asio::enable_if<
0913 boost::asio::is_convertible<
0914 Property,
0915 boost::asio::execution::relationship_t
0916 >::value
0917 >::type
0918 >
0919 {
0920 static constexpr bool is_valid = true;
0921 static constexpr bool is_noexcept = true;
0922 typedef boost::asio::execution::relationship_t result_type;
0923 };
0924
0925 template <typename Allocator, unsigned int Bits>
0926 struct query_member<
0927 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0928 boost::asio::execution::occupancy_t
0929 >
0930 {
0931 static constexpr bool is_valid = true;
0932 static constexpr bool is_noexcept = true;
0933 typedef std::size_t result_type;
0934 };
0935
0936 template <typename Allocator, unsigned int Bits>
0937 struct query_member<
0938 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0939 boost::asio::execution::context_t
0940 >
0941 {
0942 static constexpr bool is_valid = true;
0943 static constexpr bool is_noexcept = true;
0944 typedef boost::asio::thread_pool& result_type;
0945 };
0946
0947 template <typename Allocator, unsigned int Bits>
0948 struct query_member<
0949 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0950 boost::asio::execution::allocator_t<void>
0951 >
0952 {
0953 static constexpr bool is_valid = true;
0954 static constexpr bool is_noexcept = true;
0955 typedef Allocator result_type;
0956 };
0957
0958 template <typename Allocator, unsigned int Bits, typename OtherAllocator>
0959 struct query_member<
0960 boost::asio::thread_pool::basic_executor_type<Allocator, Bits>,
0961 boost::asio::execution::allocator_t<OtherAllocator>
0962 >
0963 {
0964 static constexpr bool is_valid = true;
0965 static constexpr bool is_noexcept = true;
0966 typedef Allocator result_type;
0967 };
0968
0969 #endif
0970
0971 }
0972
0973 namespace execution {
0974
0975 template <>
0976 struct is_executor<thread_pool> : false_type
0977 {
0978 };
0979
0980 }
0981
0982 #endif
0983
0984 }
0985 }
0986
0987 #include <boost/asio/detail/pop_options.hpp>
0988
0989 #include <boost/asio/impl/thread_pool.hpp>
0990 #if defined(BOOST_ASIO_HEADER_ONLY)
0991 # include <boost/asio/impl/thread_pool.ipp>
0992 #endif
0993
0994 #endif