IAtari
Genetic algorithm generating AI capable to play Atari2600 games.
slave.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <string>
3 #include <memory>
4 #include <functional>
5 #include "message.hpp"
6 #include <boost/asio/io_service.hpp>
7 #include <boost/asio/ip/tcp.hpp>
8 #include <boost/asio/spawn.hpp>
9 #include "connection.hpp"
10 #include <chrono>
11 #include <unistd.h>
12 
13 template <typename Res, typename Params>
14 class slave
15 {
16  std::string master_name;
17  std::string port;
18  using worker = std::function<message::result<Res>(const message::request<Params>&)>;
19  worker producer;
20  int duration;
21 
22 public:
23  slave(const std::string& master_name, int port, worker w, int duration = 1e6)
24  : master_name(master_name), port(std::to_string(port)), producer(w), duration(duration)
25  {
26  }
27  void run();
29 };
30 
31 template <typename Res, typename Params>
33 {
34  using namespace boost;
35  asio::io_service io_service;
36  asio::spawn(io_service,
37  [&](asio::yield_context yield)
38  {
39  try
40  {
41  auto start = std::chrono::system_clock::now();
42  char machine[512];
43  gethostname(machine, 512);
44  machine[511] = 0;
45  std::time_t start_time = std::chrono::system_clock::to_time_t(start);
46  std::cout << "slave starts work on machine "
47  << machine
48  << " at time "
49  << std::ctime(&start_time)
50  << std::endl;
51  asio::ip::tcp::resolver resolver(io_service);
52  asio::ip::tcp::resolver::query query(master_name, port);
53  asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
54  asio::ip::tcp::socket socket(io_service);
55  asio::async_connect(socket, endpoint_iterator, yield);
56  connection connection(std::move(socket));
57  while (connection.get_socket().is_open())
58  {
59  system::error_code ec;
61  connection.async_read(request, yield[ec]);
62  if (ec)
63  {
64  std::cout << "slave can't read on machine "
65  << machine
66  << std::endl;
67  break;
68  }
69  message::result<Res> res = do_work(request);
70  connection.async_write(res, yield[ec]);
71  if (ec)
72  {
73  std::cout << "slave can't write on machine "
74  << machine
75  << std::endl;
76  break;
77  }
78  auto end = std::chrono::system_clock::now();
79  int elapsed_minutes = std::chrono::duration<double>(end - start).count() / 60.0;
80  if (elapsed_minutes >= duration)
81  {
82  std::time_t end_time = std::chrono::system_clock::to_time_t(end);
83  std::cout << "slave has finished on machine "
84  << machine
85  << " at time "
86  << std::ctime(&end_time)
87  << std::endl;
88  break;
89  }
90  }
91  }
92  catch (std::exception& e)
93  {
94  std::cout << e.what() << std::endl;
95  }
96  });
97  io_service.run();
98 }
99 
100 template <typename Res, typename Params>
102 {
103  message::result<Res> res = producer(request);
104  res.id = request.id;
105  return res;
106 }
void async_read(T &t, boost::asio::yield_context yield)
Definition: connection.hpp:66
message::result< Res > do_work(const message::request< Params > &)
Definition: slave.hpp:101
int id
Definition: message.hpp:9
slave(const std::string &master_name, int port, worker w, int duration=1e6)
Definition: slave.hpp:23
boost::asio::ip::tcp::socket & get_socket()
Definition: connection.hpp:46
void run()
Definition: slave.hpp:32
int id
Definition: message.hpp:26
Definition: message.hpp:24
void async_write(const T &t, boost::asio::yield_context yield)
Definition: connection.hpp:52
Definition: connection.hpp:13
Definition: message.hpp:7
Definition: slave.hpp:14