+/** \ingroup msg_gos_functions
+ * \brief Checks whether a communication is done, and if yes, finalizes it.
+ * \param comm the communication to test
+ * \return TRUE if the communication is finished
+ * (but it may have failed, use MSG_comm_get_status() to know its status)
+ * or FALSE if the communication is not finished yet
+ * If the status is FALSE, don't forget to use MSG_process_sleep() after the test.
+ */
+int MSG_comm_test(msg_comm_t comm)
+{
+ xbt_ex_t e;
+ int finished = 0;
+ TRY {
+ finished = SIMIX_req_comm_test(comm->s_comm);
+ }
+ CATCH(e) {
+ switch (e.category) {
+
+ case host_error:
+ comm->status = MSG_HOST_FAILURE;
+ finished = 1;
+ break;
+
+ case network_error:
+ comm->status = MSG_TRANSFER_FAILURE;
+ finished = 1;
+ break;
+
+ case timeout_error:
+ comm->status = MSG_TIMEOUT;
+ finished = 1;
+ break;
+
+ default:
+ RETHROW;
+ }
+ xbt_ex_free(e);
+ }
+
+ return finished;
+}
+
+/** \ingroup msg_gos_functions
+ * \brief This function checks if a communication is finished.
+ * \param comms a vector of communications
+ * \return the position of the finished communication if any
+ * (but it may have failed, use MSG_comm_get_status() to know its status),
+ * or -1 if none is finished
+ */
+int MSG_comm_testany(xbt_dynar_t comms)
+{
+ xbt_ex_t e;
+ int finished_index = -1;
+
+ /* create the equivalent dynar with SIMIX objects */
+ xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
+ msg_comm_t comm;
+ unsigned int cursor;
+ xbt_dynar_foreach(comms, cursor, comm) {
+ xbt_dynar_push(s_comms, &comm->s_comm);
+ }
+
+ MSG_error_t status = MSG_OK;
+ TRY {
+ finished_index = SIMIX_req_comm_testany(s_comms);
+ }
+ CATCH(e) {
+ switch (e.category) {
+
+ case host_error:
+ finished_index = e.value;
+ status = MSG_HOST_FAILURE;
+ break;
+
+ case network_error:
+ finished_index = e.value;
+ status = MSG_TRANSFER_FAILURE;
+ break;
+
+ case timeout_error:
+ finished_index = e.value;
+ status = MSG_TIMEOUT;
+ break;
+
+ default:
+ RETHROW;
+ }
+ xbt_ex_free(e);
+ }
+ xbt_dynar_free(&s_comms);
+
+ if (finished_index != -1) {
+ comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
+ /* the communication is finished */
+ comm->status = status;
+ }
+
+ return finished_index;
+}
+
+/** \ingroup msg_gos_functions
+ * \brief Destroys a communication.
+ * \param comm the communication to destroy.
+ */
+void MSG_comm_destroy(msg_comm_t comm)
+{
+ if (comm->task_received != NULL
+ && *comm->task_received != NULL
+ && MSG_comm_get_status(comm) == MSG_OK) {
+ (*comm->task_received)->simdata->isused = 0;
+ }
+
+ /* FIXME auto-destroy comms from SIMIX to avoid this request */
+ SIMIX_req_comm_destroy(comm->s_comm);
+ free(comm);
+}
+
+/** \ingroup msg_gos_functions
+ * \brief Wait for the completion of a communication.
+ *
+ * It takes two parameters.
+ * \param comm the communication to wait.
+ * \param timeout Wait until the communication terminates or the timeout occurs
+ * \return MSG_error_t
+ */
+MSG_error_t MSG_comm_wait(msg_comm_t comm, double timeout)
+{
+ xbt_ex_t e;
+ TRY {
+ SIMIX_req_comm_wait(comm->s_comm, timeout);
+
+ if (comm->task_received != NULL) {
+ /* I am the receiver */
+ (*comm->task_received)->simdata->isused = 0;
+ }
+
+ /* FIXME: these functions are not traceable */
+ }
+ CATCH(e) {
+ switch (e.category) {
+ case host_error:
+ comm->status = MSG_HOST_FAILURE;
+ break;
+ case network_error:
+ comm->status = MSG_TRANSFER_FAILURE;
+ break;
+ case timeout_error:
+ comm->status = MSG_TIMEOUT;
+ break;
+ default:
+ RETHROW;
+ }
+ xbt_ex_free(e);
+ }
+
+ return comm->status;
+}
+
+/** \ingroup msg_gos_functions
+* \brief This function is called by a sender and permit to wait for each communication
+*
+* \param comm a vector of communication
+* \param nb_elem is the size of the comm vector
+* \param timeout for each call of MSG_comm_wait
+*/
+void MSG_comm_waitall(msg_comm_t * comm, int nb_elem, double timeout)
+{
+ int i = 0;
+ for (i = 0; i < nb_elem; i++) {
+ MSG_comm_wait(comm[i], timeout);
+ }
+}
+
+/** \ingroup msg_gos_functions
+ * \brief This function waits for the first communication finished in a list.
+ * \param comms a vector of communications
+ * \return the position of the first finished communication
+ * (but it may have failed, use MSG_comm_get_status() to know its status)
+ */
+int MSG_comm_waitany(xbt_dynar_t comms)
+{
+ xbt_ex_t e;
+ int finished_index = -1;
+
+ /* create the equivalent dynar with SIMIX objects */
+ xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
+ msg_comm_t comm;
+ unsigned int cursor;
+ xbt_dynar_foreach(comms, cursor, comm) {
+ xbt_dynar_push(s_comms, &comm->s_comm);
+ }
+
+ MSG_error_t status = MSG_OK;
+ TRY {
+ finished_index = SIMIX_req_comm_waitany(s_comms);
+ }
+ CATCH(e) {
+ switch (e.category) {
+
+ case host_error:
+ finished_index = e.value;
+ status = MSG_HOST_FAILURE;
+ break;
+
+ case network_error:
+ finished_index = e.value;
+ status = MSG_TRANSFER_FAILURE;
+ break;
+
+ case timeout_error:
+ finished_index = e.value;
+ status = MSG_TIMEOUT;
+ break;
+
+ default:
+ RETHROW;
+ }
+ xbt_ex_free(e);
+ }
+
+ xbt_assert0(finished_index != -1, "WaitAny returned -1");
+ xbt_dynar_free(&s_comms);
+
+ comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
+ /* the communication is finished */
+ comm->status = status;
+
+ return finished_index;
+}
+
+/**
+ * \ingroup msg_gos_functions
+ * \brief Returns the error (if any) that occured during a finished communication.
+ * \param comm a finished communication
+ * \return the status of the communication, or MSG_OK if no error occured
+ * during the communication
+ */
+MSG_error_t MSG_comm_get_status(msg_comm_t comm) {
+
+ return comm->status;
+}
+
+m_task_t MSG_comm_get_task(msg_comm_t comm)
+{
+ xbt_assert0(comm, "Invalid parameter");
+
+ return comm->task_received ? *comm->task_received : comm->task_sent;
+}