修复webserver死锁
This commit is contained in:
@@ -10,15 +10,21 @@
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
namespace renderive::web {
|
||||
namespace {
|
||||
Gallery_View_Input gallery_input(const Event& event) {
|
||||
@@ -133,6 +139,56 @@ trantor::EventLoop* automatic_render_loop() {
|
||||
return thread.getLoop();
|
||||
}
|
||||
}
|
||||
namespace detail {
|
||||
class Automatic_Render_Executor final {
|
||||
public:
|
||||
Automatic_Render_Executor() {
|
||||
const std::size_t worker_count = renderive::scheduling::scheduler_concurrency();
|
||||
workers_.reserve(worker_count);
|
||||
for (std::size_t index = 0; index < worker_count; ++index) {
|
||||
workers_.emplace_back([this](std::stop_token stop) {
|
||||
run(stop);
|
||||
});
|
||||
}
|
||||
}
|
||||
~Automatic_Render_Executor() {
|
||||
for (auto& worker : workers_)
|
||||
worker.request_stop();
|
||||
condition_.notify_all();
|
||||
}
|
||||
void enqueue(std::function<void()> task) {
|
||||
{
|
||||
std::lock_guard lock(mutex_);
|
||||
tasks_.push_back(std::move(task));
|
||||
}
|
||||
condition_.notify_one();
|
||||
}
|
||||
private:
|
||||
void run(std::stop_token stop) {
|
||||
for (;;) {
|
||||
std::function<void()> task;
|
||||
{
|
||||
std::unique_lock lock(mutex_);
|
||||
if (!condition_.wait(lock, stop, [this] {
|
||||
return !tasks_.empty();
|
||||
}))
|
||||
return;
|
||||
task = std::move(tasks_.front());
|
||||
tasks_.pop_front();
|
||||
}
|
||||
task();
|
||||
}
|
||||
}
|
||||
std::mutex mutex_;
|
||||
std::condition_variable_any condition_;
|
||||
std::deque<std::function<void()>> tasks_;
|
||||
std::vector<std::jthread> workers_;
|
||||
};
|
||||
Automatic_Render_Executor& automatic_render_executor() {
|
||||
static Automatic_Render_Executor executor;
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
struct Gallery_Plot_Session::Impl : std::enable_shared_from_this<Gallery_Plot_Session::Impl> {
|
||||
using Clock = std::chrono::steady_clock;
|
||||
explicit Impl(bool enable_automatic_low_latency)
|
||||
@@ -247,7 +303,7 @@ struct Gallery_Plot_Session::Impl : std::enable_shared_from_this<Gallery_Plot_Se
|
||||
}
|
||||
auto self = shared_from_this();
|
||||
try {
|
||||
renderive::scheduling::enqueue_task([self = std::move(self), generation] {
|
||||
detail::automatic_render_executor().enqueue([self = std::move(self), generation] {
|
||||
self->run_automatic_render(generation);
|
||||
});
|
||||
} catch (...) {
|
||||
|
||||
Reference in New Issue
Block a user