#include #include #include #include #include #include #include "caf/actor_system.hpp" #include "caf/actor_system_config.hpp" #include "caf/event_based_actor.hpp" #include "caf/exec_main.hpp" #include "caf/function_view.hpp" #include "caf/init_global_meta_objects.hpp" #include "caf/policy/select_all.hpp" #include "caf/scoped_actor.hpp" #include "caf/typed_actor.hpp" #include "caf/typed_event_based_actor.hpp" CAF_BEGIN_TYPE_ID_BLOCK(fan_out_request, first_custom_type_id) CAF_ADD_ATOM(fan_out_request, row_atom) CAF_ADD_ATOM(fan_out_request, column_atom) CAF_ADD_ATOM(fan_out_request, average_atom) CAF_END_TYPE_ID_BLOCK(fan_out_request) using std::endl; using std::chrono::seconds; using namespace caf; /// A simple actor for storing an integer value. using cell = typed_actor< // Writes a new value. result(put_atom, int), // Reads the value. result(get_atom)>; /// An for storing a 2-dimensional matrix of integers. using matrix = typed_actor< // Writes a new value to given cell (x-coordinate, y-coordinate, new-value). result(put_atom, int, int, int), // Reads from given cell. result(get_atom, int, int), // Computes the average for given row. result(get_atom, average_atom, row_atom, int), // Computes the average for given column. result(get_atom, average_atom, column_atom, int)>; struct cell_state { int value = 0; static constexpr const char* name = "cell"; }; cell::behavior_type cell_actor(cell::stateful_pointer self) { return { [=](put_atom, int val) { self->state.value = val; }, [=](get_atom) { return self->state.value; }, }; } struct matrix_state { using row_type = std::vector; std::vector rows; static constexpr const char* name = "matrix"; }; matrix::behavior_type matrix_actor(matrix::stateful_pointer self, int rows, int columns) { // Spawn all cells and return our behavior. self->state.rows.resize(rows); for (int row = 0; row < rows; ++row) { auto& row_vec = self->state.rows[row]; row_vec.resize(columns); for (int column = 0; column < columns; ++column) row_vec[column] = self->spawn(cell_actor); } return { [=](put_atom put, int row, int column, int val) { assert(row < rows && column < columns); return self->delegate(self->state.rows[row][column], put, val); }, [=](get_atom get, int row, int column) { assert(row < rows && column < columns); return self->delegate(self->state.rows[row][column], get); }, [=](get_atom get, average_atom, row_atom, int row) { assert(row < rows); auto rp = self->make_response_promise(); auto& row_vec = self->state.rows[row]; self->fan_out_request(row_vec, infinite, get) .then( [=](std::vector xs) mutable { assert(xs.size() == static_cast(columns)); rp.deliver(std::accumulate(xs.begin(), xs.end(), 0.0) / columns); }, [=](error& err) mutable { rp.deliver(std::move(err)); }); return rp; }, // --(rst-fan-out-begin)-- [=](get_atom get, average_atom, column_atom, int column) { assert(column < columns); std::vector columns; columns.reserve(rows); auto& rows_vec = self->state.rows; for (int row = 0; row < rows; ++row) columns.emplace_back(rows_vec[row][column]); auto rp = self->make_response_promise(); self->fan_out_request(columns, infinite, get) .then( [=](std::vector xs) mutable { assert(xs.size() == static_cast(rows)); rp.deliver(std::accumulate(xs.begin(), xs.end(), 0.0) / rows); }, [=](error& err) mutable { rp.deliver(std::move(err)); }); return rp; }, // --(rst-fan-out-end)-- }; } std::ostream& operator<<(std::ostream& out, const expected& x) { if (x) return out << *x; return out << to_string(x.error()); } void caf_main(actor_system& sys) { // Spawn our matrix. static constexpr int rows = 3; static constexpr int columns = 6; auto mx = sys.spawn(matrix_actor, rows, columns); auto f = make_function_view(mx); // Set cells in our matrix to these values: // 2 4 8 16 32 64 // 3 9 27 81 243 729 // 4 16 64 256 1024 4096 for (int row = 0; row < rows; ++row) for (int column = 0; column < columns; ++column) f(put_atom_v, row, column, (int) pow(row + 2, column + 1)); // Print out matrix. for (int row = 0; row < rows; ++row) { for (int column = 0; column < columns; ++column) std::cout << std::setw(4) << f(get_atom_v, row, column) << ' '; std::cout << '\n'; } // Print out AVG for each row and column. for (int row = 0; row < rows; ++row) std::cout << "AVG(row " << row << ") = " << f(get_atom_v, average_atom_v, row_atom_v, row) << '\n'; for (int column = 0; column < columns; ++column) std::cout << "AVG(column " << column << ") = " << f(get_atom_v, average_atom_v, column_atom_v, column) << '\n'; } CAF_MAIN(id_block::fan_out_request)