// #include "mpi_test_incl.h"
#include <mpi.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    int rank = 0, buf;
    int provided;
    int retErr  = MPI_SUCCESS;

    MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
    assert(MPI_THREAD_MULTIPLE == provided);

    MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN); // return an exception instead of Fatal Error, which finishes execution of all processes.
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (rank == 0){
        MPI_Request request;
        MPI_Status  status;
        for (int i=1; i<10; ++i) {
            retErr = MPI_Irecv(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request);
            if (retErr != MPI_SUCCESS) {
                printf("Error in initiating irecv !!! \n");
            }
            retErr = MPI_Wait(&request, &status);
            if (retErr != MPI_SUCCESS) {
                printf("Error with sender !!! \n");
            }
            else {
                printf("Got %d \n", buf);
            }
        }
    } else {
        for (int i=1; i<10; ++i) {
            buf = i * 1000;
            retErr = MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
            if (i==5) {
                printf("Calling abort\n");
                MPI_Abort(MPI_COMM_WORLD, 1);
            }
        }
    }

    retErr = MPI_Finalize();
    return 0;
}
