+ * \brief Test whether there is a pending communication on a channel, and who sent it.
+ *
+ * It takes one parameter.
+ * \param channel the channel on which the agent should be
+ listening. This value has to be >=0 and < than the maximal
+ number of channels fixed with MSG_set_channel_number().
+ * \return -1 if there is no pending communication and the PID of the process who sent it otherwise
+ */
+int MSG_task_probe_from(m_channel_t channel)
+{
+ m_host_t h = NULL;
+ xbt_fifo_item_t item;
+ m_task_t t;
+
+ xbt_assert1((channel>=0) && (channel < msg_global->max_channel),"Invalid channel %d",channel);
+ CHECK_HOST();
+
+ h = MSG_host_self();
+
+ DEBUG2("Probing on channel %d (%s)", channel,h->name);
+
+ item = xbt_fifo_get_first_item(h->simdata->mbox[channel]);
+ if ( (!item) || (!(t = xbt_fifo_get_item_content(item))) )
+ return -1;
+
+ return MSG_process_get_PID(t->simdata->sender);
+}
+
+/** \ingroup msg_gos_functions
+ * \brief Wait for at most \a max_duration second for a task reception
+ on \a channel. *\a PID is updated with the PID of the first process
+ that triggered this event if any.
+ *
+ * It takes three parameters:
+ * \param channel the channel on which the agent should be
+ listening. This value has to be >=0 and < than the maximal.
+ number of channels fixed with MSG_set_channel_number().
+ * \param PID a memory location for storing an int.
+ * \param max_duration the maximum time to wait for a task before
+ giving up. In the case of a reception, *\a PID will be updated
+ with the PID of the first process to send a task.
+ * \return #MSG_HOST_FAILURE if the host is shut down in the meantime
+ and #MSG_OK otherwise.
+ */
+MSG_error_t MSG_channel_select_from(m_channel_t channel, double max_duration,
+ int *PID)
+{
+ m_host_t h = NULL;
+ simdata_host_t h_simdata = NULL;
+ xbt_fifo_item_t item;
+ m_task_t t;
+ int first_time = 1;
+ smx_cond_t cond;
+
+ xbt_assert1((channel>=0) && (channel < msg_global->max_channel),"Invalid channel %d",channel);
+ if(PID) {
+ *PID = -1;
+ }
+
+ if(max_duration==0.0) {
+ *PID = MSG_task_probe_from(channel);
+ MSG_RETURN(MSG_OK);
+ } else {
+ CHECK_HOST();
+ h = MSG_host_self();
+ h_simdata = h->simdata;
+
+ DEBUG2("Probing on channel %d (%s)", channel,h->name);
+ while(!(item = xbt_fifo_get_first_item(h->simdata->mbox[channel]))) {
+ if(max_duration>0) {
+ if(!first_time) {
+ MSG_RETURN(MSG_OK);
+ }
+ }
+ SIMIX_mutex_lock(h_simdata->mutex);
+ xbt_assert1(!(h_simdata->sleeping[channel]),
+ "A process is already blocked on this channel %d", channel);
+ cond = SIMIX_cond_init();
+ h_simdata->sleeping[channel] = cond; /* I'm waiting. Wake me up when you're ready */
+ if(max_duration>0) {
+ SIMIX_cond_wait_timeout(cond,h_simdata->mutex, max_duration);
+ } else {
+ SIMIX_cond_wait(cond,h_simdata->mutex);
+ }
+ SIMIX_cond_destroy(cond);
+ SIMIX_mutex_unlock(h_simdata->mutex);
+ if(SIMIX_host_get_state(h_simdata->s_host)==0) {
+ MSG_RETURN(MSG_HOST_FAILURE);
+ }
+ h_simdata->sleeping[channel] = NULL;
+ first_time = 0;
+ }
+ if (!item || !(t = xbt_fifo_get_item_content(item))) {
+ MSG_RETURN(MSG_OK);
+ }
+ if(PID) {
+ *PID = MSG_process_get_PID(t->simdata->sender);
+ }
+ MSG_RETURN(MSG_OK);
+ }
+}
+
+
+/** \ingroup msg_gos_functions
+
+ * \brief Return the number of tasks waiting to be received on a \a
+ channel and sent by \a host.
+ *
+ * It takes two parameters.
+ * \param channel the channel on which the agent should be
+ listening. This value has to be >=0 and < than the maximal
+ number of channels fixed with MSG_set_channel_number().
+ * \param host the host that is to be watched.
+ * \return the number of tasks waiting to be received on \a channel
+ and sent by \a host.
+ */
+int MSG_task_probe_from_host(int channel, m_host_t host)
+{
+ xbt_fifo_item_t item;
+ m_task_t t;
+ int count = 0;
+ m_host_t h = NULL;
+
+ xbt_assert1((channel>=0) && (channel < msg_global->max_channel),"Invalid channel %d",channel);
+ CHECK_HOST();
+ h = MSG_host_self();
+
+ DEBUG2("Probing on channel %d (%s)", channel,h->name);
+
+ xbt_fifo_foreach(h->simdata->mbox[channel],item,t,m_task_t) {
+ if(t->simdata->source==host) count++;
+ }
+
+ return count;
+}
+
+/** \ingroup msg_gos_functions \brief Put a task on a channel of an
+ * host (with a timeout on the waiting of the destination host) and
+ * waits for the end of the transmission.