|
||||
File indexing completed on 2025-01-18 09:29:28
0001 // 0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 0003 // 0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0006 // 0007 // Official repository: https://github.com/boostorg/beast 0008 // 0009 0010 #ifndef BOOST_BEAST_MULTI_BUFFER_HPP 0011 #define BOOST_BEAST_MULTI_BUFFER_HPP 0012 0013 #include <boost/beast/core/detail/config.hpp> 0014 #include <boost/beast/core/detail/allocator.hpp> 0015 #include <boost/asio/buffer.hpp> 0016 #include <boost/core/empty_value.hpp> 0017 #include <boost/intrusive/list.hpp> 0018 #include <boost/type_traits/type_with_alignment.hpp> 0019 #include <iterator> 0020 #include <limits> 0021 #include <memory> 0022 #include <type_traits> 0023 0024 namespace boost { 0025 namespace beast { 0026 0027 /** A dynamic buffer providing sequences of variable length. 0028 0029 A dynamic buffer encapsulates memory storage that may be 0030 automatically resized as required, where the memory is 0031 divided into two regions: readable bytes followed by 0032 writable bytes. These memory regions are internal to 0033 the dynamic buffer, but direct access to the elements 0034 is provided to permit them to be efficiently used with 0035 I/O operations. 0036 0037 The implementation uses a sequence of one or more byte 0038 arrays of varying sizes to represent the readable and 0039 writable bytes. Additional byte array objects are 0040 appended to the sequence to accommodate changes in the 0041 desired size. The behavior and implementation of this 0042 container is most similar to `std::deque`. 0043 0044 Objects of this type meet the requirements of <em>DynamicBuffer</em> 0045 and have the following additional properties: 0046 0047 @li A mutable buffer sequence representing the readable 0048 bytes is returned by @ref data when `this` is non-const. 0049 0050 @li Buffer sequences representing the readable and writable 0051 bytes, returned by @ref data and @ref prepare, may have 0052 length greater than one. 0053 0054 @li A configurable maximum size may be set upon construction 0055 and adjusted afterwards. Calls to @ref prepare that would 0056 exceed this size will throw `std::length_error`. 0057 0058 @li Sequences previously obtained using @ref data remain 0059 valid after calls to @ref prepare or @ref commit. 0060 0061 @tparam Allocator The allocator to use for managing memory. 0062 */ 0063 template<class Allocator> 0064 class basic_multi_buffer 0065 #if ! BOOST_BEAST_DOXYGEN 0066 : private boost::empty_value<Allocator> 0067 #endif 0068 { 0069 // Fancy pointers are not supported 0070 static_assert(std::is_pointer<typename 0071 std::allocator_traits<Allocator>::pointer>::value, 0072 "Allocator must use regular pointers"); 0073 0074 static bool constexpr default_nothrow = 0075 std::is_nothrow_default_constructible<Allocator>::value; 0076 0077 // Storage for the list of buffers representing the input 0078 // and output sequences. The allocation for each element 0079 // contains `element` followed by raw storage bytes. 0080 class element 0081 : public boost::intrusive::list_base_hook< 0082 boost::intrusive::link_mode< 0083 boost::intrusive::normal_link>> 0084 { 0085 using size_type = typename 0086 detail::allocator_traits<Allocator>::size_type; 0087 0088 size_type const size_; 0089 0090 public: 0091 element(element const&) = delete; 0092 0093 explicit 0094 element(size_type n) noexcept 0095 : size_(n) 0096 { 0097 } 0098 0099 size_type 0100 size() const noexcept 0101 { 0102 return size_; 0103 } 0104 0105 char* 0106 data() const noexcept 0107 { 0108 return const_cast<char*>( 0109 reinterpret_cast<char const*>(this + 1)); 0110 } 0111 }; 0112 0113 template<bool> 0114 class subrange; 0115 0116 using size_type = typename 0117 detail::allocator_traits<Allocator>::size_type; 0118 0119 using align_type = typename 0120 boost::type_with_alignment<alignof(element)>::type; 0121 0122 using rebind_type = typename 0123 beast::detail::allocator_traits<Allocator>:: 0124 template rebind_alloc<align_type>; 0125 0126 using alloc_traits = 0127 beast::detail::allocator_traits<rebind_type>; 0128 0129 using list_type = typename boost::intrusive::make_list< 0130 element, boost::intrusive::constant_time_size<false>>::type; 0131 0132 using iter = typename list_type::iterator; 0133 0134 using const_iter = typename list_type::const_iterator; 0135 0136 using pocma = typename 0137 alloc_traits::propagate_on_container_move_assignment; 0138 0139 using pocca = typename 0140 alloc_traits::propagate_on_container_copy_assignment; 0141 0142 static_assert(std::is_base_of<std::bidirectional_iterator_tag, 0143 typename std::iterator_traits<iter>::iterator_category>::value, 0144 "BidirectionalIterator type requirements not met"); 0145 0146 static_assert(std::is_base_of<std::bidirectional_iterator_tag, 0147 typename std::iterator_traits<const_iter>::iterator_category>::value, 0148 "BidirectionalIterator type requirements not met"); 0149 0150 std::size_t max_; 0151 list_type list_; // list of allocated buffers 0152 iter out_; // element that contains out_pos_ 0153 size_type in_size_ = 0; // size of the input sequence 0154 size_type in_pos_ = 0; // input offset in list_.front() 0155 size_type out_pos_ = 0; // output offset in *out_ 0156 size_type out_end_ = 0; // output end offset in list_.back() 0157 0158 public: 0159 #if BOOST_BEAST_DOXYGEN 0160 /// The ConstBufferSequence used to represent the readable bytes. 0161 using const_buffers_type = __implementation_defined__; 0162 0163 /// The MutableBufferSequence used to represent the writable bytes. 0164 using mutable_buffers_type = __implementation_defined__; 0165 #else 0166 using const_buffers_type = subrange<false>; 0167 0168 using mutable_buffers_type = subrange<true>; 0169 #endif 0170 0171 /// The type of allocator used. 0172 using allocator_type = Allocator; 0173 0174 /// Destructor 0175 ~basic_multi_buffer(); 0176 0177 /** Constructor 0178 0179 After construction, @ref capacity will return zero, and 0180 @ref max_size will return the largest value which may 0181 be passed to the allocator's `allocate` function. 0182 */ 0183 basic_multi_buffer() noexcept(default_nothrow); 0184 0185 /** Constructor 0186 0187 After construction, @ref capacity will return zero, and 0188 @ref max_size will return the specified value of `limit`. 0189 0190 @param limit The desired maximum size. 0191 */ 0192 explicit 0193 basic_multi_buffer( 0194 std::size_t limit) noexcept(default_nothrow); 0195 0196 /** Constructor 0197 0198 After construction, @ref capacity will return zero, and 0199 @ref max_size will return the largest value which may 0200 be passed to the allocator's `allocate` function. 0201 0202 @param alloc The allocator to use for the object. 0203 0204 @esafe 0205 0206 No-throw guarantee. 0207 */ 0208 explicit 0209 basic_multi_buffer(Allocator const& alloc) noexcept; 0210 0211 /** Constructor 0212 0213 After construction, @ref capacity will return zero, and 0214 @ref max_size will return the specified value of `limit`. 0215 0216 @param limit The desired maximum size. 0217 0218 @param alloc The allocator to use for the object. 0219 0220 @esafe 0221 0222 No-throw guarantee. 0223 */ 0224 basic_multi_buffer( 0225 std::size_t limit, Allocator const& alloc) noexcept; 0226 0227 /** Move Constructor 0228 0229 The container is constructed with the contents of `other` 0230 using move semantics. The maximum size will be the same 0231 as the moved-from object. 0232 0233 Buffer sequences previously obtained from `other` using 0234 @ref data or @ref prepare remain valid after the move. 0235 0236 @param other The object to move from. After the move, the 0237 moved-from object will have zero capacity, zero readable 0238 bytes, and zero writable bytes. 0239 0240 @esafe 0241 0242 No-throw guarantee. 0243 */ 0244 basic_multi_buffer(basic_multi_buffer&& other) noexcept; 0245 0246 /** Move Constructor 0247 0248 Using `alloc` as the allocator for the new container, the 0249 contents of `other` are moved. If `alloc != other.get_allocator()`, 0250 this results in a copy. The maximum size will be the same 0251 as the moved-from object. 0252 0253 Buffer sequences previously obtained from `other` using 0254 @ref data or @ref prepare become invalid after the move. 0255 0256 @param other The object to move from. After the move, 0257 the moved-from object will have zero capacity, zero readable 0258 bytes, and zero writable bytes. 0259 0260 @param alloc The allocator to use for the object. 0261 0262 @throws std::length_error if `other.size()` exceeds the 0263 maximum allocation size of `alloc`. 0264 */ 0265 basic_multi_buffer( 0266 basic_multi_buffer&& other, 0267 Allocator const& alloc); 0268 0269 /** Copy Constructor 0270 0271 This container is constructed with the contents of `other` 0272 using copy semantics. The maximum size will be the same 0273 as the copied object. 0274 0275 @param other The object to copy from. 0276 0277 @throws std::length_error if `other.size()` exceeds the 0278 maximum allocation size of the allocator. 0279 */ 0280 basic_multi_buffer(basic_multi_buffer const& other); 0281 0282 /** Copy Constructor 0283 0284 This container is constructed with the contents of `other` 0285 using copy semantics and the specified allocator. The maximum 0286 size will be the same as the copied object. 0287 0288 @param other The object to copy from. 0289 0290 @param alloc The allocator to use for the object. 0291 0292 @throws std::length_error if `other.size()` exceeds the 0293 maximum allocation size of `alloc`. 0294 */ 0295 basic_multi_buffer(basic_multi_buffer const& other, 0296 Allocator const& alloc); 0297 0298 /** Copy Constructor 0299 0300 This container is constructed with the contents of `other` 0301 using copy semantics. The maximum size will be the same 0302 as the copied object. 0303 0304 @param other The object to copy from. 0305 0306 @throws std::length_error if `other.size()` exceeds the 0307 maximum allocation size of the allocator. 0308 */ 0309 template<class OtherAlloc> 0310 basic_multi_buffer(basic_multi_buffer< 0311 OtherAlloc> const& other); 0312 0313 /** Copy Constructor 0314 0315 This container is constructed with the contents of `other` 0316 using copy semantics. The maximum size will be the same 0317 as the copied object. 0318 0319 @param other The object to copy from. 0320 0321 @param alloc The allocator to use for the object. 0322 0323 @throws std::length_error if `other.size()` exceeds the 0324 maximum allocation size of `alloc`. 0325 */ 0326 template<class OtherAlloc> 0327 basic_multi_buffer( 0328 basic_multi_buffer<OtherAlloc> const& other, 0329 allocator_type const& alloc); 0330 0331 /** Move Assignment 0332 0333 The container is assigned with the contents of `other` 0334 using move semantics. The maximum size will be the same 0335 as the moved-from object. 0336 0337 Buffer sequences previously obtained from `other` using 0338 @ref data or @ref prepare remain valid after the move. 0339 0340 @param other The object to move from. After the move, 0341 the moved-from object will have zero capacity, zero readable 0342 bytes, and zero writable bytes. 0343 */ 0344 basic_multi_buffer& 0345 operator=(basic_multi_buffer&& other); 0346 0347 /** Copy Assignment 0348 0349 The container is assigned with the contents of `other` 0350 using copy semantics. The maximum size will be the same 0351 as the copied object. 0352 0353 After the copy, `this` will have zero writable bytes. 0354 0355 @param other The object to copy from. 0356 0357 @throws std::length_error if `other.size()` exceeds the 0358 maximum allocation size of the allocator. 0359 */ 0360 basic_multi_buffer& operator=( 0361 basic_multi_buffer const& other); 0362 0363 /** Copy Assignment 0364 0365 The container is assigned with the contents of `other` 0366 using copy semantics. The maximum size will be the same 0367 as the copied object. 0368 0369 After the copy, `this` will have zero writable bytes. 0370 0371 @param other The object to copy from. 0372 0373 @throws std::length_error if `other.size()` exceeds the 0374 maximum allocation size of the allocator. 0375 */ 0376 template<class OtherAlloc> 0377 basic_multi_buffer& operator=( 0378 basic_multi_buffer<OtherAlloc> const& other); 0379 0380 /// Returns a copy of the allocator used. 0381 allocator_type 0382 get_allocator() const 0383 { 0384 return this->get(); 0385 } 0386 0387 /** Set the maximum allowed capacity 0388 0389 This function changes the currently configured upper limit 0390 on capacity to the specified value. 0391 0392 @param n The maximum number of bytes ever allowed for capacity. 0393 0394 @esafe 0395 0396 No-throw guarantee. 0397 */ 0398 void 0399 max_size(std::size_t n) noexcept 0400 { 0401 max_ = n; 0402 } 0403 0404 /** Guarantee a minimum capacity 0405 0406 This function adjusts the internal storage (if necessary) 0407 to guarantee space for at least `n` bytes. 0408 0409 Buffer sequences previously obtained using @ref data remain 0410 valid, while buffer sequences previously obtained using 0411 @ref prepare become invalid. 0412 0413 @param n The minimum number of byte for the new capacity. 0414 If this value is greater than the maximum size, then the 0415 maximum size will be adjusted upwards to this value. 0416 0417 @throws std::length_error if n is larger than the maximum 0418 allocation size of the allocator. 0419 0420 @esafe 0421 0422 Strong guarantee. 0423 */ 0424 void 0425 reserve(std::size_t n); 0426 0427 /** Reallocate the buffer to fit the readable bytes exactly. 0428 0429 Buffer sequences previously obtained using @ref data or 0430 @ref prepare become invalid. 0431 0432 @esafe 0433 0434 Strong guarantee. 0435 */ 0436 void 0437 shrink_to_fit(); 0438 0439 /** Set the size of the readable and writable bytes to zero. 0440 0441 This clears the buffer without changing capacity. 0442 Buffer sequences previously obtained using @ref data or 0443 @ref prepare become invalid. 0444 0445 @esafe 0446 0447 No-throw guarantee. 0448 */ 0449 void 0450 clear() noexcept; 0451 0452 /// Exchange two dynamic buffers 0453 template<class Alloc> 0454 friend 0455 void 0456 swap( 0457 basic_multi_buffer<Alloc>& lhs, 0458 basic_multi_buffer<Alloc>& rhs) noexcept; 0459 0460 //-------------------------------------------------------------------------- 0461 0462 /// Returns the number of readable bytes. 0463 size_type 0464 size() const noexcept 0465 { 0466 return in_size_; 0467 } 0468 0469 /// Return the maximum number of bytes, both readable and writable, that can ever be held. 0470 size_type 0471 max_size() const noexcept 0472 { 0473 return max_; 0474 } 0475 0476 /// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation. 0477 std::size_t 0478 capacity() const noexcept; 0479 0480 /** Returns a constant buffer sequence representing the readable bytes 0481 0482 @note The sequence may contain multiple contiguous memory regions. 0483 */ 0484 const_buffers_type 0485 data() const noexcept; 0486 0487 /** Returns a constant buffer sequence representing the readable bytes 0488 0489 @note The sequence may contain multiple contiguous memory regions. 0490 */ 0491 const_buffers_type 0492 cdata() const noexcept 0493 { 0494 return data(); 0495 } 0496 0497 /** Returns a mutable buffer sequence representing the readable bytes. 0498 0499 @note The sequence may contain multiple contiguous memory regions. 0500 */ 0501 mutable_buffers_type 0502 data() noexcept; 0503 0504 /** Returns a mutable buffer sequence representing writable bytes. 0505 0506 Returns a mutable buffer sequence representing the writable 0507 bytes containing exactly `n` bytes of storage. Memory may be 0508 reallocated as needed. 0509 0510 All buffer sequences previously obtained using @ref prepare are 0511 invalidated. Buffer sequences previously obtained using @ref data 0512 remain valid. 0513 0514 @param n The desired number of bytes in the returned buffer 0515 sequence. 0516 0517 @throws std::length_error if `size() + n` exceeds `max_size()`. 0518 0519 @esafe 0520 0521 Strong guarantee. 0522 */ 0523 mutable_buffers_type 0524 prepare(size_type n); 0525 0526 /** Append writable bytes to the readable bytes. 0527 0528 Appends n bytes from the start of the writable bytes to the 0529 end of the readable bytes. The remainder of the writable bytes 0530 are discarded. If n is greater than the number of writable 0531 bytes, all writable bytes are appended to the readable bytes. 0532 0533 All buffer sequences previously obtained using @ref prepare are 0534 invalidated. Buffer sequences previously obtained using @ref data 0535 remain valid. 0536 0537 @param n The number of bytes to append. If this number 0538 is greater than the number of writable bytes, all 0539 writable bytes are appended. 0540 0541 @esafe 0542 0543 No-throw guarantee. 0544 */ 0545 void 0546 commit(size_type n) noexcept; 0547 0548 /** Remove bytes from beginning of the readable bytes. 0549 0550 Removes n bytes from the beginning of the readable bytes. 0551 0552 All buffers sequences previously obtained using 0553 @ref data or @ref prepare are invalidated. 0554 0555 @param n The number of bytes to remove. If this number 0556 is greater than the number of readable bytes, all 0557 readable bytes are removed. 0558 0559 @esafe 0560 0561 No-throw guarantee. 0562 */ 0563 void 0564 consume(size_type n) noexcept; 0565 0566 private: 0567 template<class OtherAlloc> 0568 friend class basic_multi_buffer; 0569 0570 template<class OtherAlloc> 0571 void copy_from(basic_multi_buffer<OtherAlloc> const&); 0572 void move_assign(basic_multi_buffer& other, std::false_type); 0573 void move_assign(basic_multi_buffer& other, std::true_type) noexcept; 0574 void copy_assign(basic_multi_buffer const& other, std::false_type); 0575 void copy_assign(basic_multi_buffer const& other, std::true_type); 0576 void swap(basic_multi_buffer&) noexcept; 0577 void swap(basic_multi_buffer&, std::true_type) noexcept; 0578 void swap(basic_multi_buffer&, std::false_type) noexcept; 0579 void destroy(list_type& list) noexcept; 0580 void destroy(const_iter it); 0581 void destroy(element& e); 0582 element& alloc(std::size_t size); 0583 void debug_check() const; 0584 }; 0585 0586 /// A typical multi buffer 0587 using multi_buffer = basic_multi_buffer<std::allocator<char>>; 0588 0589 } // beast 0590 } // boost 0591 0592 #include <boost/beast/core/impl/multi_buffer.hpp> 0593 0594 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |