Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions include/ArcadeProcess.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef ARCADE_MACHINE_PROCESS_H
#define ARCADE_MACHINE_PROCESS_H

#include <array>
#include <string>
#include <vector>
#include <stdexcept>
#include <iostream>
#include <thread>

class ArcadeProcess {
private:
std::string _command;
std::vector<std::string> _args;
std::thread _execution_context;
bool _is_running = false;
void _execute_async_thread();

public:
std::vector<std::string> output_stream;
ArcadeProcess(std::string command, std::vector<std::string> args);
bool is_running() const { return this->_is_running; }
std::string execute_sync();
void execute_async();
};

#endif
4 changes: 3 additions & 1 deletion include/ConfigData.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include <vector>
#include <fstream>
#include <cstring>
#include <experimental/filesystem>
#include "splashkit.h"

/**
Expand Down Expand Up @@ -77,4 +79,4 @@ class ConfigData

};

#endif
#endif
73 changes: 73 additions & 0 deletions src/ArcadeProcess.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "ArcadeProcess.h"

#include <array>
#include <string>
#include <vector>
#include <iostream>
#include <thread>


void ArcadeProcess::_execute_async_thread() {
// Don't allow duplicate threads to execute.
if (this->_is_running)
return;

std::string command = std::string(this->_command);
for (auto arg : this->_args)
command.append(" " + arg);

this->_is_running = true;
auto pipe = popen(command.c_str(), "r");
if (! pipe)
throw std::runtime_error("Error running process (async) `" + command + "`");

std::array<char, 256> buffer;
while (! feof(pipe)) {
if (fgets(buffer.data(), 256, pipe) != nullptr)
this->output_stream.push_back(buffer.data());
}

if (pclose(pipe) != EXIT_SUCCESS)
std::cerr << "Unable to close process (async), possible memory leak" << std::endl;

this->_is_running = false;
}

ArcadeProcess::ArcadeProcess(std::string command, std::vector<std::string> args) {
this->_command = command;
this->_args = args;
this->output_stream = std::vector<std::string>();
}

std::string ArcadeProcess::execute_sync() {
// This should never happen, but you never know...
if (this->_is_running)
throw std::runtime_error("Instance of process is already running.");

std::string command = std::string(this->_command);
for (auto arg : this->_args)
command.append(" " + arg);

this->_is_running = true;
auto pipe = popen(command.c_str(), "r");
if (! pipe)
throw std::runtime_error("Error running process `" + command + "`");

std::array<char, 256> buffer;
std::string str_buffer;
while (! feof(pipe)) {
if (fgets(buffer.data(), 256, pipe) != nullptr)
str_buffer += buffer.data();
}

if (pclose(pipe) != EXIT_SUCCESS)
std::cerr << "Unable to close process, possible memory leak" << std::endl;

this->_is_running = false;
return str_buffer;
}

void ArcadeProcess::execute_async() {
this->_execution_context = std::thread(&ArcadeProcess::_execute_async_thread, this);
this->_execution_context.detach();
}