43 boost::asio::ip::tcp::socket&
socket;
59 const std::shared_ptr<const char>& buffer,
84 boost::asio::ip::tcp::socket&
socket;
98 const std::shared_ptr<char>& buffer,
133 mutable double _average_rate;
134 mutable uint32_t _unaccounted_bytes;
138 void update_const(uint32_t bytes_transferred = 0)
const;
142 void update(uint32_t bytes_transferred = 0);
147 _unaccounted_bytes(0),
149 _time_constant(time_constant)
153 _time_constant = time_constant;
157 update_const(bytes_transferred);
159 void average_rate_meter::update_const(uint32_t bytes_transferred )
const
162 if (now <= _last_update_time)
163 _unaccounted_bytes += bytes_transferred;
166 microseconds time_since_last_update = now - _last_update_time;
167 if (time_since_last_update > _time_constant)
168 _average_rate = bytes_transferred / (_time_constant.
count() / (double)
seconds(1).
count());
171 bytes_transferred += _unaccounted_bytes;
172 double seconds_since_last_update = time_since_last_update.
count() / (double)
seconds(1).
count();
173 double rate_since_last_update = bytes_transferred / seconds_since_last_update;
174 double alpha = time_since_last_update.
count() / (double)_time_constant.
count();
175 _average_rate = rate_since_last_update * alpha + _average_rate * (1.0 - alpha);
177 _last_update_time = now;
178 _unaccounted_bytes = 0;
184 return (uint32_t)_average_rate;
218 uint32_t burstiness_in_seconds = 1);
221 virtual size_t readsome(boost::asio::ip::tcp::socket& socket,
char* buffer,
size_t length)
override;
222 virtual size_t readsome(boost::asio::ip::tcp::socket& socket,
const std::shared_ptr<char>& buffer,
size_t length,
size_t offset)
override;
223 template <
typename BufferType>
224 size_t readsome_impl(boost::asio::ip::tcp::socket& socket,
const BufferType& buffer,
size_t length,
size_t offset);
225 virtual size_t writesome(boost::asio::ip::tcp::socket& socket,
const char* buffer,
size_t length)
override;
226 virtual size_t writesome(boost::asio::ip::tcp::socket& socket,
const std::shared_ptr<const char>& buffer,
size_t length,
size_t offset)
override;
227 template <
typename BufferType>
228 size_t writesome_impl(boost::asio::ip::tcp::socket& socket,
const BufferType& buffer,
size_t length,
size_t offset);
233 uint32_t& limit_bytes_per_second,
237 uint32_t& unused_tokens);
241 uint32_t burstiness_in_seconds) :
242 _upload_bytes_per_second(upload_bytes_per_second),
243 _download_bytes_per_second(download_bytes_per_second),
244 _burstiness_in_seconds(burstiness_in_seconds),
246 _read_tokens(_download_bytes_per_second),
247 _unused_read_tokens(0),
248 _write_tokens(_upload_bytes_per_second),
249 _unused_write_tokens(0)
281 template <
typename BufferType>
299 bytes_read = completion_promise->
wait();
327 template <
typename BufferType>
330 size_t bytes_written;
345 bytes_written = completion_promise->
wait();
360 return bytes_written;
378 catch (
const timeout_exception&)
399 catch (
const timeout_exception&)
406 uint32_t& limit_bytes_per_second,
410 uint32_t& unused_tokens)
413 std::copy(operations_for_next_iteration.begin(),
414 operations_for_next_iteration.end(),
415 std::back_inserter(operations_in_progress));
416 operations_for_next_iteration.clear();
420 if (limit_bytes_per_second)
422 microseconds time_since_last_iteration = this_iteration_start_time - last_iteration_start_time;
423 if (time_since_last_iteration >
seconds(1))
424 time_since_last_iteration =
seconds(1);
428 tokens += (uint32_t)((limit_bytes_per_second * time_since_last_iteration.
count()) / 1000000);
429 tokens += unused_tokens;
436 std::vector<rate_limited_operation*> operations_sorted_by_length;
437 operations_sorted_by_length.reserve(operations_in_progress.size());
439 operations_sorted_by_length.push_back(operation_data);
440 std::sort(operations_sorted_by_length.begin(), operations_sorted_by_length.end(),
is_operation_shorter());
443 uint32_t bytes_remaining_to_allocate = tokens;
444 while (!operations_sorted_by_length.empty())
446 uint32_t bytes_permitted_for_this_operation = bytes_remaining_to_allocate / operations_sorted_by_length.size();
447 uint32_t bytes_allocated_for_this_operation = std::min<size_t>(operations_sorted_by_length.back()->length, bytes_permitted_for_this_operation);
448 operations_sorted_by_length.back()->permitted_length = bytes_allocated_for_this_operation;
449 bytes_remaining_to_allocate -= bytes_allocated_for_this_operation;
450 operations_sorted_by_length.pop_back();
452 tokens = bytes_remaining_to_allocate;
455 for (
auto iter = operations_in_progress.begin(); iter != operations_in_progress.end();)
457 if ((*iter)->permitted_length > 0)
460 iter = operations_in_progress.erase(iter);
473 for (
auto iter = operations_in_progress.begin();
474 iter != operations_in_progress.end();)
477 iter = operations_in_progress.erase(iter);
482 last_iteration_start_time = this_iteration_start_time;
488 my(new detail::rate_limiting_group_impl(upload_bytes_per_second, download_bytes_per_second, burstiness_in_seconds))
498 return my->_actual_upload_rate.get_average_rate();
503 return my->_actual_download_rate.get_average_rate();
508 my->_actual_upload_rate.set_time_constant(time_constant);
509 my->_actual_download_rate.set_time_constant(time_constant);
514 my->_upload_bytes_per_second = upload_bytes_per_second;
519 return my->_upload_bytes_per_second;
524 my->_download_bytes_per_second = download_bytes_per_second;
529 return my->_download_bytes_per_second;