From 2c67bbf6091477a09d280c322539cbaf1b6e4a8e Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Tue, 21 Jul 2020 04:40:28 -0300
Subject: [PATCH] service/sockets: Add worker pool abstraction

Manage worker threads with an easy to use abstraction.
We can expand this to support thread deletion in the future.
---
 .../hle/service/sockets/blocking_worker.h     | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/src/core/hle/service/sockets/blocking_worker.h b/src/core/hle/service/sockets/blocking_worker.h
index 7bd486530..31ef6b821 100644
--- a/src/core/hle/service/sockets/blocking_worker.h
+++ b/src/core/hle/service/sockets/blocking_worker.h
@@ -10,6 +10,7 @@
 #include <string_view>
 #include <thread>
 #include <variant>
+#include <vector>
 
 #include <fmt/format.h>
 
@@ -129,4 +130,33 @@ private:
     std::atomic_bool is_available{true};
 };
 
+template <class Service, class... Types>
+class BlockingWorkerPool {
+    using Worker = BlockingWorker<Service, Types...>;
+
+public:
+    explicit BlockingWorkerPool(Core::System& system_, Service* service_)
+        : system{system_}, service{service_} {}
+
+    /// Returns a captured worker thread, creating new ones if necessary
+    Worker* CaptureWorker() {
+        for (auto& worker : workers) {
+            if (worker->TryCapture()) {
+                return worker.get();
+            }
+        }
+        auto new_worker = Worker::Create(system, service, fmt::format("BSD:{}", workers.size()));
+        [[maybe_unused]] const bool success = new_worker->TryCapture();
+        ASSERT(success);
+
+        return workers.emplace_back(std::move(new_worker)).get();
+    }
+
+private:
+    Core::System& system;
+    Service* const service;
+
+    std::vector<std::unique_ptr<Worker>> workers;
+};
+
 } // namespace Service::Sockets