+ smx_req_t req;
+
+ while ((req = xbt_fifo_shift(action->request_list))) {
+
+ /* If a waitany request is waiting for this action to finish, then remove
+ it from the other actions in the waitany list. Afterwards, get the
+ position of the actual action in the waitany request's actions dynar and
+ return it as the result of the call */
+ if (req->call == REQ_COMM_WAITANY) {
+ SIMIX_waitany_req_remove_from_actions(req);
+ req->comm_waitany.result = xbt_dynar_search(req->comm_waitany.comms, &action);
+ }
+
+ /* If the action is still in a rendez-vous point then remove from it */
+ if (action->comm.rdv)
+ SIMIX_rdv_remove(action->comm.rdv, action);
+
+ DEBUG1("SIMIX_comm_finish: action state = %d", action->state);
+
+ /* Check out for errors */
+ switch (action->state) {
+
+ case SIMIX_DONE:
+ DEBUG1("Communication %p complete!", action);
+ SIMIX_comm_copy_data(action);
+ break;
+
+ case SIMIX_SRC_TIMEOUT:
+ TRY {
+ THROW0(timeout_error, 0, "Communication timeouted because of sender");
+ }
+ CATCH(req->issuer->running_ctx->exception) {
+ req->issuer->doexception = 1;
+ }
+ break;
+
+ case SIMIX_DST_TIMEOUT:
+ TRY {
+ THROW0(timeout_error, 0, "Communication timeouted because of receiver");
+ }
+ CATCH(req->issuer->running_ctx->exception) {
+ req->issuer->doexception = 1;
+ }
+ break;
+
+ case SIMIX_SRC_HOST_FAILURE:
+ TRY {
+ if (req->issuer == action->comm.src_proc)
+ THROW0(host_error, 0, "Host failed");
+ else
+ THROW0(network_error, 0, "Remote peer failed");
+ }
+ CATCH(req->issuer->running_ctx->exception) {
+ req->issuer->doexception = 1;
+ }
+ break;
+
+ case SIMIX_DST_HOST_FAILURE:
+ TRY {
+ if (req->issuer == action->comm.dst_proc)
+ THROW0(host_error, 0, "Host failed");
+ else
+ THROW0(network_error, 0, "Remote peer failed");
+ }
+ CATCH(req->issuer->running_ctx->exception) {
+ req->issuer->doexception = 1;
+ }
+ break;
+
+ case SIMIX_LINK_FAILURE:
+ TRY {
+ DEBUG5("Link failure in action %p between '%s' and '%s': posting an exception to the issuer: %s (%p)",
+ action, action->comm.src_proc->smx_host->name, action->comm.dst_proc->smx_host->name,
+ req->issuer->name, req->issuer);
+ THROW0(network_error, 0, "Link failure");
+ }
+ CATCH(req->issuer->running_ctx->exception) {
+ req->issuer->doexception = 1;
+ }
+ break;
+
+ default:
+ THROW_IMPOSSIBLE;
+ }
+ req->issuer->waiting_action = NULL;
+ SIMIX_request_answer(req);
+ }
+}
+
+void SIMIX_post_comm(smx_action_t action)
+{
+ /* Update action state */
+ if (action->comm.src_timeout &&
+ surf_workstation_model->action_state_get(action->comm.src_timeout) == SURF_ACTION_DONE)
+ action->state = SIMIX_SRC_TIMEOUT;
+ else if (action->comm.dst_timeout &&
+ surf_workstation_model->action_state_get(action->comm.dst_timeout) == SURF_ACTION_DONE)
+ action->state = SIMIX_DST_TIMEOUT;
+ else if (action->comm.src_timeout &&
+ surf_workstation_model->action_state_get(action->comm.src_timeout) == SURF_ACTION_FAILED)
+ action->state = SIMIX_SRC_HOST_FAILURE;
+ else if (action->comm.dst_timeout &&
+ surf_workstation_model->action_state_get(action->comm.dst_timeout) == SURF_ACTION_FAILED)
+ action->state = SIMIX_DST_HOST_FAILURE;
+ else if (action->comm.surf_comm &&
+ surf_workstation_model->action_state_get(action->comm.surf_comm) == SURF_ACTION_FAILED)
+ action->state = SIMIX_LINK_FAILURE;
+ else
+ action->state = SIMIX_DONE;
+
+ DEBUG1("SIMIX_post_comm: action state = %d", action->state);
+
+ /* After this point the surf actions associated with the simix communicate
+ action are no longer needed, thus we delete them. */
+ SIMIX_comm_destroy_internal_actions(action);
+
+ /* If there are requests associated with the action, then answer them */
+ if (xbt_fifo_size(action->request_list))
+ SIMIX_comm_finish(action);
+}
+
+void SIMIX_comm_cancel(smx_action_t action)
+{
+ /* If the action is a waiting state means that it is still in a rdv */
+ /* so remove from it and delete it */
+ if (action->state == SIMIX_WAITING) {
+ SIMIX_rdv_remove(action->comm.rdv, action);
+ action->state = SIMIX_FAILED;
+ } else {
+ surf_workstation_model->action_cancel(action->comm.surf_comm);
+ }