1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
#ifndef UNIX_PROCESS_H
#define UNIX_PROCESS_H
#if defined(__WXGTK__)||defined(__WXOSX__)
#include <exception>
#include <functional>
#include <iostream>
#include <memory>
#include <sys/wait.h>
#include <thread>
#include <unistd.h>
#include <wx/thread.h>
#include <wx/msgqueue.h>
#include <atomic>
#include <wx/event.h>
// Wrapping pipe in a class makes sure they are closed when we leave scope
class CPipe
{
private:
int fd[2];
public:
const inline int read_fd() const { return fd[0]; }
const inline int write_fd() const { return fd[1]; }
CPipe() { pipe(fd); }
void close()
{
::close(fd[0]);
::close(fd[1]);
}
~CPipe() { close(); }
};
class UnixProcess
{
private:
CPipe m_childStdin;
CPipe m_childStdout;
CPipe m_childStderr;
std::thread* m_writerThread = nullptr;
std::thread* m_readerThread = nullptr;
wxMessageQueue<std::string> m_outgoingQueue;
std::atomic_bool m_goingDown;
wxEvtHandler* m_owner = nullptr;
protected:
// sync operations
static bool ReadAll(int fd, std::string& content, int timeoutMilliseconds);
static bool Write(int fd, const std::string& message, std::atomic_bool& shutdown);
void StartWriterThread();
void StartReaderThread();
public:
int child_pid = -1;
UnixProcess(wxEvtHandler* owner, const wxArrayString& args);
~UnixProcess();
// wait for process termination
int Wait();
// Async calls with callbacks
void Write(const std::string& message);
// stop the running process
void Stop();
/**
* @brief stop sending events from the process
*/
void Detach();
};
#endif // defined(__WXGTK__)||defined(__WXOSX__)
#endif // UNIX_PROCESS_H
|