yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
editor_control_queue.h
Go to the documentation of this file.
1#ifndef YAZE_APP_SERVICE_EDITOR_CONTROL_QUEUE_H_
2#define YAZE_APP_SERVICE_EDITOR_CONTROL_QUEUE_H_
3
4#include <atomic>
5#include <chrono>
6#include <functional>
7#include <future>
8#include <memory>
9#include <mutex>
10#include <queue>
11#include <string>
12
13#include "absl/status/status.h"
14#include "absl/status/statusor.h"
15
16namespace yaze::app {
17
18// Worker requests are applied only by ProcessOne on the main frame thread.
19// A command that times out before execution can never run on a later frame.
21 public:
22 absl::StatusOr<std::string> Submit(
23 std::string json,
24 std::chrono::milliseconds queue_timeout = std::chrono::seconds(5)) {
25 auto request = std::make_shared<Request>();
26 request->json = std::move(json);
27 auto result = request->result.get_future();
28 {
29 std::lock_guard<std::mutex> lock(mutex_);
30 if (requests_.size() >= 16) {
31 return absl::ResourceExhaustedError("Editor command queue is full");
32 }
33 requests_.push(request);
34 }
35 if (result.wait_for(queue_timeout) != std::future_status::ready) {
36 int queued = 0;
37 if (request->state.compare_exchange_strong(queued, 2)) {
38 return absl::DeadlineExceededError(
39 "Editor did not process the command; cancelled without execution");
40 }
41 // Once execution starts, return its actual result, not a false timeout.
42 }
43 return result.get();
44 }
45
47 const std::function<std::string(const std::string&)>& action) {
48 std::shared_ptr<Request> request;
49 {
50 std::lock_guard<std::mutex> lock(mutex_);
51 if (requests_.empty())
52 return;
53 request = requests_.front();
54 requests_.pop();
55 }
56 int queued = 0;
57 if (request->state.compare_exchange_strong(queued, 1)) {
58 try {
59 request->result.set_value(action(request->json));
60 } catch (...) {
61 // Release the waiting HTTP worker even if the callback throws.
62 request->result.set_value(
63 R"({"protocol":"yaze-editor-control/v1","status":"error","http_status":500,"error":"Editor command failed"})");
64 }
65 }
66 }
67
68 bool pending() const {
69 std::lock_guard<std::mutex> lock(mutex_);
70 return !requests_.empty();
71 }
72
73 private:
74 struct Request {
75 std::string json;
76 std::promise<std::string> result;
77 // 0 queued, 1 running, 2 cancelled before execution.
78 std::atomic<int> state{0};
79 };
80 mutable std::mutex mutex_;
81 std::queue<std::shared_ptr<Request>> requests_;
82};
83
84} // namespace yaze::app
85#endif
std::queue< std::shared_ptr< Request > > requests_
void ProcessOne(const std::function< std::string(const std::string &)> &action)
absl::StatusOr< std::string > Submit(std::string json, std::chrono::milliseconds queue_timeout=std::chrono::seconds(5))