Skip to content
Communicator.hpp 1.52 KiB
Newer Older
#pragma once

#include <vector>

#include "gsl/multi_span"
#include <boost/container/static_vector.hpp>
#include "Configuration.hpp"
#include "MpiEnvironment.hpp"
#include "State.hpp"
#include "Util.hpp"

class Communicator {
	constexpr static std::size_t NoNeighbors{8};

	CommunicationMode _commMode;
	std::vector<int> _neighbors;
	std::vector<int> _sizes;
	std::vector<MPI_Datatype> _sendTypes;
	const std::vector<MPI_Datatype>& _recvTypes{_sendTypes};
	std::vector<MPI_Aint> _sendDisplacements;
	std::vector<MPI_Aint> _recvDisplacements;
	MPI_Comm _commDistGraph{MPI_COMM_NULL};

	MPI_Datatype _haloRowType;
	MPI_Datatype _haloColumnType;
	MPI_Datatype _haloCornerType{MPI_CHAR};

	void ReportInvalidCommunicationModeError();

	Communicator() = default;
	Communicator(const MpiEnvironment& env, CommunicationMode commMode,
	             const Size& gridSize, const Size& tileSize);
	~Communicator();
	void swap(Communicator& first, Communicator& second);

	Communicator(Communicator&) = delete;
	Communicator& operator=(Communicator&) = delete;
	Communicator(Communicator&& other) noexcept;
	Communicator& operator=(Communicator&& other) noexcept;
	void Communicate(gsl::multi_span<State, -1, -1>& model);

	class MpiRequest {
		boost::container::static_vector<MPI_Request, NoNeighbors * 2> _reqs;
		bool finished{};

	  public:
		MpiRequest(
		    boost::container::static_vector<MPI_Request, NoNeighbors * 2> reqs);
		void Wait();
		~MpiRequest();
	MpiRequest AsyncCommunicate(gsl::multi_span<State, -1, -1>& model);