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 
19 template <typename Res, typename Params>
25 class slave
26 {
27  std::string master_name;
28  std::string port;
29  using worker = std::function<message::result<Res>(const message::request<Params>&)>;
31  int duration;
33 public:
43  slave(const std::string& master_name, int port, worker w, int duration = 1e6)
44  : master_name(master_name), port(std::to_string(port)), producer(w), duration(duration)
45  {
46  }
47 
56  void run();
57 
66 };
67 
68 template <typename Res, typename Params>
70 {
71  using namespace boost;
72  asio::io_service io_service;
73  asio::spawn(io_service,
74  [&](asio::yield_context yield)
75  {
76  try
77  {
78  auto start = std::chrono::system_clock::now();
79  char machine[512];
80  gethostname(machine, 512);
81  machine[511] = 0;
82  std::time_t start_time = std::chrono::system_clock::to_time_t(start);
83  std::cout << "slave starts work on machine "
84  << machine
85  << " at time "
86  << std::ctime(&start_time)
87  << std::endl;
88  asio::ip::tcp::resolver resolver(io_service);
89  asio::ip::tcp::resolver::query query(master_name, port);
90  asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
91  asio::ip::tcp::socket socket(io_service);
92  asio::async_connect(socket, endpoint_iterator, yield);
93  connection connection(std::move(socket));
94  while (connection.get_socket().is_open())
95  {
96  system::error_code ec;
98  connection.async_read(request, yield[ec]);
99  if (ec)
100  {
101  std::cout << "slave can't read on machine "
102  << machine
103  << std::endl;
104  break;
105  }
106  message::result<Res> res = do_work(request);
107  connection.async_write(res, yield[ec]);
108  if (ec)
109  {
110  std::cout << "slave can't write on machine "
111  << machine
112  << std::endl;
113  break;
114  }
115  auto end = std::chrono::system_clock::now();
116  int elapsed_minutes = std::chrono::duration<double>(end - start).count() / 60.0;
117  if (elapsed_minutes >= duration)
118  {
119  std::time_t end_time = std::chrono::system_clock::to_time_t(end);
120  std::cout << "slave has finished on machine "
121  << machine
122  << " at time "
123  << std::ctime(&end_time)
124  << std::endl;
125  break;
126  }
127  }
128  }
129  catch (std::exception& e)
130  {
131  std::cout << e.what() << std::endl;
132  }
133  });
134  io_service.run();
135 }
136 
137 template <typename Res, typename Params>
139 {
140  message::result<Res> res = producer(request);
141  res.id = request.id;
142  return res;
143 }
message::result< Res > do_work(const message::request< Params > &)
Test an agent.
Definition: slave.hpp:138
int id
Definition: message.hpp:26
slave(const std::string &master_name, int port, worker w, int duration=1e6)
Standard constructor.
Definition: slave.hpp:43
int duration
Definition: slave.hpp:31
worker producer
Definition: slave.hpp:30
void run()
In a coroutine, initialize a connection with the master throught a socket and perform as many test as...
Definition: slave.hpp:69
boost::asio::ip::tcp::socket & get_socket()
Return the associated socket.
Definition: connection.hpp:84
int id
Definition: message.hpp:56
Represent the score performed by a freshly tested agent, can be (un)serialized.
Definition: message.hpp:54
void async_write(const T &t, boost::asio::yield_context yield)
Write a value through the associated socket.
Definition: connection.hpp:96
Handle serializable representations of agents.
std::string master_name
Definition: slave.hpp:27
std::function< message::result< Res >(const message::request< Params > &)> worker
Definition: slave.hpp:29
void async_read(T &t, boost::asio::yield_context yield)
Read a value through the associated socket. May return an error if the inner inputStream can't be rea...
Definition: connection.hpp:116
Handle networking.
Definition: connection.hpp:25
Represent an agent to be tested, can be (un)serialized.
Definition: message.hpp:24
Handle networking.
Slave part of the algorithm, perform test on agents.
Definition: slave.hpp:25
std::string port
Definition: slave.hpp:28