+static void print_communications_pattern(xbt_dynar_t comms_pattern){
+ unsigned int cursor = 0;
+ mc_comm_pattern_t current_comm;
+ xbt_dynar_foreach(comms_pattern, cursor, current_comm){
+ if(current_comm->type == SIMIX_COMM_SEND)
+ XBT_INFO("[(%lu) %s -> (%lu) %s] %s ", current_comm->src_proc, current_comm->src_host, current_comm->dst_proc, current_comm->dst_host, "iSend");
+ else
+ XBT_INFO("[(%lu) %s <- (%lu) %s] %s ", current_comm->dst_proc, current_comm->dst_host, current_comm->src_proc, current_comm->src_host, "iRecv");
+ }
+}
+
+static void visited_state_free(mc_visited_state_t state){
+ if(state){
+ MC_free_snapshot(state->system_state);
+ xbt_free(state);
+ }
+}
+
+static void visited_state_free_voidp(void *s){
+ visited_state_free((mc_visited_state_t) * (void **) s);
+}
+
+/** \brief Save the current state
+ *
+ * \return Snapshot of the current state.
+ */
+static mc_visited_state_t visited_state_new(){
+
+ mc_visited_state_t new_state = NULL;
+ new_state = xbt_new0(s_mc_visited_state_t, 1);
+ new_state->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
+ new_state->nb_processes = xbt_swag_size(simix_global->process_list);
+ new_state->system_state = MC_take_snapshot(mc_stats->expanded_states);
+ new_state->num = mc_stats->expanded_states;
+ new_state->other_num = -1;
+
+ return new_state;
+
+}
+
+/** \brief Find a suitable subrange of candidate duplicates for a given state
+ *
+ * \param all_ pairs dynamic array of states with candidate duplicates of the current state;
+ * \param pair current state;
+ * \param min (output) index of the beginning of the the subrange
+ * \param max (output) index of the enf of the subrange
+ *
+ * Given a suitably ordered array of state, this function extracts a subrange
+ * (with index *min <= i <= *max) with candidate duplicates of the given state.
+ * This function uses only fast discriminating criterions and does not use the
+ * full state comparison algorithms.
+ *
+ * The states in all_pairs MUST be ordered using a (given) weak order
+ * (based on nb_processes and heap_bytes_used).
+ * The subrange is the subrange of "equivalence" of the given state.
+ */
+static int get_search_interval(xbt_dynar_t all_states, mc_visited_state_t state, int *min, int *max){
+ XBT_VERB("Searching interval for state %i: nd_processes=%zu heap_bytes_used=%zu",
+ state->num, (size_t)state->nb_processes, (size_t)state->heap_bytes_used);
+
+ int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
+
+ MC_SET_MC_HEAP;
+
+ int cursor = 0, previous_cursor, next_cursor;
+ mc_visited_state_t state_test;
+ int start = 0;
+ int end = xbt_dynar_length(all_states) - 1;
+
+ while(start <= end){
+ cursor = (start + end) / 2;
+ state_test = (mc_visited_state_t)xbt_dynar_get_as(all_states, cursor, mc_visited_state_t);
+ if(state_test->nb_processes < state->nb_processes){
+ start = cursor + 1;
+ }else if(state_test->nb_processes > state->nb_processes){
+ end = cursor - 1;
+ }else{
+ if(state_test->heap_bytes_used < state->heap_bytes_used){
+ start = cursor +1;
+ }else if(state_test->heap_bytes_used > state->heap_bytes_used){
+ end = cursor - 1;
+ }else{
+ *min = *max = cursor;
+ previous_cursor = cursor - 1;
+ while(previous_cursor >= 0){
+ state_test = (mc_visited_state_t)xbt_dynar_get_as(all_states, previous_cursor, mc_visited_state_t);
+ if(state_test->nb_processes != state->nb_processes || state_test->heap_bytes_used != state->heap_bytes_used)
+ break;
+ *min = previous_cursor;
+ previous_cursor--;
+ }
+ next_cursor = cursor + 1;
+ while(next_cursor < xbt_dynar_length(all_states)){
+ state_test = (mc_visited_state_t)xbt_dynar_get_as(all_states, next_cursor, mc_visited_state_t);
+ if(state_test->nb_processes != state->nb_processes || state_test->heap_bytes_used != state->heap_bytes_used)
+ break;
+ *max = next_cursor;
+ next_cursor++;
+ }
+ if(!raw_mem_set)
+ MC_SET_STD_HEAP;
+ return -1;
+ }
+ }
+ }
+
+ if(!raw_mem_set)
+ MC_SET_STD_HEAP;
+
+ return cursor;
+}
+
+/** \brief Take a snapshot the current state and process it.
+ *
+ * \return number of the duplicate state or -1 (not visited)
+ */