#pragma once #include "common.hpp" #include "data.hpp" #include "device.hpp" #include #include #include #include namespace saw { template class data_server final : public i_data_server { private: our> device_; std::map>> values_; public: static constexpr std::pair class_id{schema_hash::apply(), schema_hash::apply()}; std::pair get_class_id() const override { return class_id; } data_server(our> device__): device_{std::move(device__)} {} error_or send(const data& dat, id store_id){ auto ins = values_.emplace(std::make_pair(store_id.get_value(), data>{dat})); if(!ins.second){ return make_error(); } return make_error("Allocate not implemented. Since we don't actually do any device copies."); return make_void(); } error_or allocate(const data::MetaSchema, Encoding>& dat, id store_id){ return make_error("Allocate not implemented"); return make_void(); } error_or> receive(id store_id){ return make_error("Receive not implemented"); } error_or erase(id store_id){ return make_error("Erase not implemented"); return make_void(); } error_or>>> find(id store_id){ auto find_res = values_.find(store_id.get_value()); if(find_res == values_.end()){ return make_error(); } return {(find_res.second)}; } }; template class data_server, Encoding, rmt::Hip> { private: /** * Device context class */ our> device_; /** * Store for the data the server manages. */ typename impl::data_server_redux, typename tmpl_reduce>::type >::type values_; public: /** * Main constructor */ data_server(our> device__): device_{std::move(device__)} {} /** * Get data which we will store. */ template error_or send(const data& dat, id store_id){ return make_error(); /* auto& vals = std::get>>>(values_); auto eoval = device_->template copy_to_device(dat); if(eoval.is_error()){ auto& err = eoval.get_error(); return std::move(err); } auto& val = eoval.get_value(); try { auto insert_res = vals.insert(std::make_pair(store_id.get_value(), std::move(val))); if(!insert_res.second){ return make_error(); } }catch ( std::exception& ){ return make_error(); } return void_t{}; */ } template error_or allocate(const data::MetaSchema, Encoding>& dat, id store_id){ return make_error(); /* auto& vals = std::get>>>(values_); auto eoval = device_->template allocate_on_device(dat); if(eoval.is_error()){ auto& err = eoval.get_error(); return std::move(err); } auto& val = eoval.get_value(); try { auto insert_res = vals.insert(std::make_pair(store_id.get_value(), std::move(val))); if(!insert_res.second){ return make_error(); } }catch ( std::exception& ){ return make_error(); } return void_t{}; */ } /** * Requests data from the server */ template error_or> receive(id store_id){ auto& vals = std::get>>>(values_); auto find_res = vals.find(store_id.get_value()); if(find_res == vals.end()){ return make_error(); } auto& dat = find_res->second; return make_error(); } /** * Request an erase of the stored data */ template error_or erase(id store_id){ auto& vals = std::get>>(values_); auto erase_op = vals.erase(store_id.get_value()); if(erase_op == 0u){ return make_error(); } return void_t{}; } /** * Get the stored data on the server side for immediate use. * Insert operations may invalidate the pointer. */ template error_or>*> find(id store_id){ auto& vals = std::get>>(values_); auto find_res = vals.find(store_id.get_value()); if(find_res == vals.end()){ return make_error(); } return &(find_res.second); } }; /** * Client for transporting data to remote and receiving data back */ template class data_client, Encoding, rmt::Hip> { private: /** * Corresponding server for this client */ data_server, Encoding, rmt::Hip>* srv_; /** * The next id for identifying issues on the remote side. */ uint64_t next_id_; public: /** * Main constructor */ data_client(data_server, Encoding, rmt::Hip>& srv__): srv_{&srv__}, next_id_{0u} {} /** * Send data to the remote. */ template error_or> send(const data& dat){ id dat_id{next_id_}; auto eov = srv_->send(dat, dat_id); if(eov.is_error()){ auto& err = eov.get_error(); return std::move(err); } ++next_id_; return dat_id; } /** * Receive data */ template conveyor> receive(id dat_id){ auto eov = srv_->receive(dat_id); if(eov.is_error()){ auto& err = eov.get_error(); return std::move(err); } auto& val = eov.get_value(); return std::move(val); } /** * Erase data */ template error_or erase(id dat_id){ return srv_->erase(dat_id); } }; }