Repository navigation
Expand file tree
/
Copy pathhttp2_dispatch.cpp
More file actions
73 lines (67 loc) · 2.11 KB
/
Copy pathhttp2_dispatch.cpp
File metadata and controls
73 lines (67 loc) · 2.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/* Copyright (C) 2026 Sebastiano Merlino; SPDX-License-Identifier: LGPL-2.1-or-later */
#include <httpserver/detail/http2_dispatch.hpp>
#include <utility>
namespace httpserver::detail {
const void*& counted_drain_slot() {
thread_local const void* identity = nullptr;
return identity;
}
auto http2_dispatch::post(handler work) -> void {
bool schedule = false;
{
std::lock_guard lock(mutex_);
if (retired_) return;
if (count_ == queue_.size()) {
retired_ = true;
} else {
queue_[(head_ + count_) % queue_.size()] = std::move(work);
++count_;
}
schedule = !scheduled_;
scheduled_ = true;
}
if (schedule) workers_.post([self = shared_from_this()] { self->run_one(); });
}
auto http2_dispatch::retire() -> void {
std::array<handler, 16> abandoned;
{
std::lock_guard lock(mutex_);
retired_ = true;
abandoned.swap(queue_);
count_ = 0;
}
}
auto http2_dispatch::run_one() -> void {
handler work;
std::array<handler, 16> abandoned;
{
std::lock_guard lock(mutex_);
if (retired_) {
abandoned.swap(queue_);
count_ = 0;
work = std::move(terminal_);
} else if (count_) {
work = std::move(queue_[head_]);
head_ = (head_ + 1) % queue_.size();
--count_;
}
}
const auto previous_drain = counted_drain_slot();
counted_drain_slot() = drain_;
const auto previous = current_executor_slot();
auto lifetime = std::move(current_task_executor_lifetime());
current_executor_slot() = this;
current_task_executor_lifetime() = shared_from_this();
if (work) work();
counted_drain_slot() = previous_drain;
current_executor_slot() = previous;
current_task_executor_lifetime() = std::move(lifetime);
bool schedule;
{
std::lock_guard lock(mutex_);
schedule = count_ || (retired_ && terminal_);
scheduled_ = schedule;
}
if (schedule) workers_.post([self = shared_from_this()] { self->run_one(); });
}
} // namespace httpserver::detail