/ src / ipc / libmultiprocess / example / example.cpp
example.cpp
 1  // Copyright (c) The Bitcoin Core developers
 2  // Distributed under the MIT software license, see the accompanying
 3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 4  
 5  #include <init.capnp.h>
 6  #include <init.capnp.proxy.h>
 7  
 8  #include <cstring> // IWYU pragma: keep
 9  #include <filesystem>
10  #include <fstream>
11  #include <future>
12  #include <iostream>
13  #include <kj/async.h>
14  #include <kj/common.h>
15  #include <memory>
16  #include <mp/proxy-io.h>
17  #include <mp/util.h>
18  #include <stdexcept>
19  #include <string>
20  #include <thread>
21  #include <tuple>
22  #include <vector>
23  
24  namespace fs = std::filesystem;
25  
26  static auto Spawn(mp::EventLoop& loop, const std::string& process_argv0, const std::string& new_exe_name)
27  {
28      int pid;
29      const int fd = mp::SpawnProcess(pid, [&](int fd) -> std::vector<std::string> {
30          fs::path path = process_argv0;
31          path.remove_filename();
32          path.append(new_exe_name);
33          return {path.string(), std::to_string(fd)};
34      });
35      return std::make_tuple(mp::ConnectStream<InitInterface>(loop, fd), pid);
36  }
37  
38  static void LogPrint(mp::LogMessage log_data)
39  {
40      if (log_data.level == mp::Log::Raise) throw std::runtime_error(log_data.message);
41      std::ofstream("debug.log", std::ios_base::app) << log_data.message << std::endl;
42  }
43  
44  int main(int argc, char** argv)
45  {
46      if (argc != 1) {
47          std::cout << "Usage: mpexample\n";
48          return 1;
49      }
50  
51      std::promise<mp::EventLoop*> promise;
52      std::thread loop_thread([&] {
53          mp::EventLoop loop("mpexample", LogPrint);
54          promise.set_value(&loop);
55          loop.loop();
56      });
57      mp::EventLoop* loop = promise.get_future().get();
58  
59      auto [printer_init, printer_pid] = Spawn(*loop, argv[0], "mpprinter");
60      auto [calc_init, calc_pid] = Spawn(*loop, argv[0], "mpcalculator");
61      auto calc = calc_init->makeCalculator(printer_init->makePrinter());
62      while (true) {
63          std::string eqn;
64          std::cout << "Enter the equation, or \"exit\" to quit: ";
65          std::getline(std::cin, eqn);
66          if (eqn == "exit") break;
67          calc->solveEquation(eqn);
68      }
69      calc.reset();
70      calc_init.reset();
71      mp::WaitProcess(calc_pid);
72      printer_init.reset();
73      mp::WaitProcess(printer_pid);
74      loop_thread.join();
75      std::cout << "Bye!" << std::endl;
76      return 0;
77  }