// Copyright 2005 Douglas Gregor.

// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// Message Passing Interface 1.1 -- Section 4.4. Broadcast

#include <boost/mpi/collectives/broadcast.hpp>
#include <boost/mpi/skeleton_and_content.hpp>
#include <boost/mpi/detail/point_to_point.hpp>
#include <boost/mpi/environment.hpp>

namespace boost { namespace mpi {

template<>
void
broadcast<const packed_oarchive>(const communicator& comm,
                                 const packed_oarchive& oa,
                                 int root)
{
  // Only the root can broadcast the packed_oarchive
  assert(comm.rank() == root);

  int size = comm.size();
  if (size < 2) return;

  // Determine maximum tag value
  int tag = environment::collectives_tag();

  // Broadcast data to all nodes
  std::vector<MPI_Request> requests(size * 2);
  int num_requests = 0;
  for (int dest = 0; dest < size; ++dest) {
    if (dest != root) {
      // Build up send requests for each child send.
      num_requests += detail::packed_archive_isend(comm, dest, tag, oa,
                                                   &requests[num_requests], 2);
    }
  }

  // Complete all of the sends
  BOOST_MPI_CHECK_RESULT(MPI_Waitall,
                         (num_requests, &requests[0], MPI_STATUSES_IGNORE));
}

template<>
void
broadcast<packed_oarchive>(const communicator& comm, packed_oarchive& oa,
                           int root)
{
  broadcast(comm, const_cast<const packed_oarchive&>(oa), root);
}

template<>
void
broadcast<packed_iarchive>(const communicator& comm, packed_iarchive& ia,
                           int root)
{
  int size = comm.size();
  if (size < 2) return;

  // Determine maximum tag value
  int tag = environment::collectives_tag();

  // Receive data from the root.
  if (comm.rank() != root) {
    MPI_Status status;
    detail::packed_archive_recv(comm, root, tag, ia, status);
  } else {
    // Broadcast data to all nodes
    std::vector<MPI_Request> requests(size * 2);
    int num_requests = 0;
    for (int dest = 0; dest < size; ++dest) {
      if (dest != root) {
        // Build up send requests for each child send.
        num_requests += detail::packed_archive_isend(comm, dest, tag, ia,
                                                     &requests[num_requests],
                                                     2);
      }
    }

    // Complete all of the sends
    BOOST_MPI_CHECK_RESULT(MPI_Waitall,
                           (num_requests, &requests[0], MPI_STATUSES_IGNORE));
  }
}

template<>
void
broadcast<const packed_skeleton_oarchive>(const communicator& comm,
                                          const packed_skeleton_oarchive& oa,
                                          int root)
{
  broadcast(comm, oa.get_skeleton(), root);
}

template<>
void
broadcast<packed_skeleton_oarchive>(const communicator& comm,
                                    packed_skeleton_oarchive& oa, int root)
{
  broadcast(comm, oa.get_skeleton(), root);
}

template<>
void
broadcast<packed_skeleton_iarchive>(const communicator& comm,
                                    packed_skeleton_iarchive& ia, int root)
{
  broadcast(comm, ia.get_skeleton(), root);
}

template<>
void broadcast<content>(const communicator& comm, content& c, int root)
{
  broadcast(comm, const_cast<const content&>(c), root);
}

template<>
void broadcast<const content>(const communicator& comm, const content& c,
                              int root)
{
#ifdef LAM_MPI
  if (comm.size() < 2)
    return;

  // Some versions of LAM/MPI behave badly when broadcasting using
  // MPI_BOTTOM, so we'll instead use manual send/recv operations.
  if (comm.rank() == root) {
    for (int p = 0; p < comm.size(); ++p) {
      if (p != root) {
        BOOST_MPI_CHECK_RESULT(MPI_Send,
                               (MPI_BOTTOM, 1, c.get_mpi_datatype(),
                                p, environment::collectives_tag(), comm));
      }
    }
  } else {
    BOOST_MPI_CHECK_RESULT(MPI_Recv,
                           (MPI_BOTTOM, 1, c.get_mpi_datatype(),
                            root, environment::collectives_tag(),
                            comm, MPI_STATUS_IGNORE));
  }
#else
  BOOST_MPI_CHECK_RESULT(MPI_Bcast,
                         (MPI_BOTTOM, 1, c.get_mpi_datatype(),
                          root, comm));
#endif
}

} } // end namespace boost::mpi
