1 // 2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // Official repository: https://github.com/boostorg/beast 8 // 9 10 #ifndef BOOST_BEAST_CORE_DETAIL_STREAM_BASE_HPP 11 #define BOOST_BEAST_CORE_DETAIL_STREAM_BASE_HPP 12 13 #include <boost/asio/steady_timer.hpp> 14 #include <boost/assert.hpp> 15 #include <boost/core/exchange.hpp> 16 #include <chrono> 17 #include <cstdint> 18 #include <utility> 19 20 namespace boost { 21 namespace beast { 22 namespace detail { 23 24 struct any_endpoint 25 { 26 template<class Error, class Endpoint> 27 bool operator ()boost::beast::detail::any_endpoint28 operator()( 29 Error const&, Endpoint const&) const noexcept 30 { 31 return true; 32 } 33 }; 34 35 struct stream_base 36 { 37 using clock_type = std::chrono::steady_clock; 38 using time_point = typename 39 std::chrono::steady_clock::time_point; 40 using tick_type = std::uint64_t; 41 42 struct op_state 43 { 44 net::steady_timer timer; // for timing out 45 tick_type tick = 0; // counts waits 46 bool pending = false; // if op is pending 47 bool timeout = false; // if timed out 48 49 template<class... Args> 50 explicit op_stateboost::beast::detail::stream_base::op_state51 op_state(Args&&... args) 52 : timer(std::forward<Args>(args)...) 53 { 54 } 55 }; 56 57 class pending_guard 58 { 59 bool* b_ = nullptr; 60 bool clear_ = true; 61 62 public: ~pending_guard()63 ~pending_guard() 64 { 65 if(clear_ && b_) 66 *b_ = false; 67 } 68 pending_guard()69 pending_guard() 70 : b_(nullptr) 71 , clear_(true) 72 { 73 } 74 75 explicit pending_guard(bool & b)76 pending_guard(bool& b) 77 : b_(&b) 78 { 79 // If this assert goes off, it means you are attempting 80 // to issue two of the same asynchronous I/O operation 81 // at the same time, without waiting for the first one 82 // to complete. For example, attempting two simultaneous 83 // calls to async_read_some. Only one pending call of 84 // each I/O type (read and write) is permitted. 85 // 86 BOOST_ASSERT(! *b_); 87 *b_ = true; 88 } 89 pending_guard(pending_guard && other)90 pending_guard( 91 pending_guard&& other) noexcept 92 : b_(other.b_) 93 , clear_(boost::exchange( 94 other.clear_, false)) 95 { 96 } 97 assign(bool & b)98 void assign(bool& b) 99 { 100 BOOST_ASSERT(!b_); 101 BOOST_ASSERT(clear_); 102 b_ = &b; 103 104 // If this assert goes off, it means you are attempting 105 // to issue two of the same asynchronous I/O operation 106 // at the same time, without waiting for the first one 107 // to complete. For example, attempting two simultaneous 108 // calls to async_read_some. Only one pending call of 109 // each I/O type (read and write) is permitted. 110 // 111 BOOST_ASSERT(! *b_); 112 *b_ = true; 113 } 114 115 void reset()116 reset() 117 { 118 BOOST_ASSERT(clear_); 119 if (b_) 120 *b_ = false; 121 clear_ = false; 122 } 123 }; 124 neverboost::beast::detail::stream_base125 static time_point never() noexcept 126 { 127 return (time_point::max)(); 128 } 129 130 static std::size_t constexpr no_limit = 131 (std::numeric_limits<std::size_t>::max)(); 132 }; 133 134 } // detail 135 } // beast 136 } // boost 137 138 #endif 139