mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2025-05-14 16:58:30 +00:00
ThreadPool: optional limit for jobs queue (#1741)
For very busy servers, the internal jobs queue where accepted sockets are enqueued can grow without limit. This is a problem for two reasons: - queueing too much work causes the server to respond with huge latency, resulting in repetead timeouts on the clients; it is definitely better to reject the connection early, so that the client receives the backpressure signal as soon as the queue is becoming too large - the jobs list can eventually cause an out of memory condition
This commit is contained in:
parent
31cdcc3c3a
commit
374d058de7
3 changed files with 118 additions and 10 deletions
18
httplib.h
18
httplib.h
|
@ -653,7 +653,7 @@ public:
|
|||
TaskQueue() = default;
|
||||
virtual ~TaskQueue() = default;
|
||||
|
||||
virtual void enqueue(std::function<void()> fn) = 0;
|
||||
virtual bool enqueue(std::function<void()> fn) = 0;
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
virtual void on_idle() {}
|
||||
|
@ -661,7 +661,8 @@ public:
|
|||
|
||||
class ThreadPool : public TaskQueue {
|
||||
public:
|
||||
explicit ThreadPool(size_t n) : shutdown_(false) {
|
||||
explicit ThreadPool(size_t n, size_t mqr = 0)
|
||||
: shutdown_(false), max_queued_requests_(mqr) {
|
||||
while (n) {
|
||||
threads_.emplace_back(worker(*this));
|
||||
n--;
|
||||
|
@ -671,13 +672,17 @@ public:
|
|||
ThreadPool(const ThreadPool &) = delete;
|
||||
~ThreadPool() override = default;
|
||||
|
||||
void enqueue(std::function<void()> fn) override {
|
||||
bool enqueue(std::function<void()> fn) override {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
if (max_queued_requests_ > 0 && jobs_.size() >= max_queued_requests_) {
|
||||
return false;
|
||||
}
|
||||
jobs_.push_back(std::move(fn));
|
||||
}
|
||||
|
||||
cond_.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
void shutdown() override {
|
||||
|
@ -727,6 +732,7 @@ private:
|
|||
std::list<std::function<void()>> jobs_;
|
||||
|
||||
bool shutdown_;
|
||||
size_t max_queued_requests_ = 0;
|
||||
|
||||
std::condition_variable cond_;
|
||||
std::mutex mutex_;
|
||||
|
@ -6319,7 +6325,11 @@ inline bool Server::listen_internal() {
|
|||
#endif
|
||||
}
|
||||
|
||||
task_queue->enqueue([this, sock]() { process_and_close_socket(sock); });
|
||||
if (!task_queue->enqueue(
|
||||
[this, sock]() { process_and_close_socket(sock); })) {
|
||||
detail::shutdown_socket(sock);
|
||||
detail::close_socket(sock);
|
||||
}
|
||||
}
|
||||
|
||||
task_queue->shutdown();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue