#pragma once
#include <atomic>
#include <cstddef>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <sys/types.h>
#include "protocol.hpp"
namespace nethack_mcp
{
/// Spawn and supervise one isolated NetHack worker process.
class EngineProcess
{
public:
/// Receive worker events from the reader thread.
using EventCallback = std::function<void(const Json&)>;
/// Construct an idle process supervisor.
EngineProcess() = default;
/// Stop a worker and reap it before destroying the supervisor.
~EngineProcess();
EngineProcess(const EngineProcess&) = delete;
EngineProcess& operator=(const EngineProcess&) = delete;
/// Spawn a worker and send its validated start message.
bool start(const Json& start_message, EventCallback callback,
std::string& error,
std::size_t max_diagnostic_bytes = 1024U * 1024U);
/// Send one validated input message to the worker.
bool send(const Json& message, std::string& error);
/// Request termination and wait for the child and reader threads.
void terminate(bool force = false);
/// Report whether the child has not yet been reaped.
bool running() const;
private:
void readLoop();
void diagnosticLoop(int descriptor);
std::string executablePath() const;
pid_t process_id_ = -1;
std::unique_ptr<FramedChannel> channel_;
EventCallback callback_;
std::thread reader_thread_;
std::thread diagnostic_thread_;
std::size_t max_diagnostic_bytes_ = 1024U * 1024U;
mutable std::mutex state_mutex_;
std::atomic<bool> running_ = false;
};
} // namespace nethack_mcp