void biosal_assembly_vertex_set_flag(struct biosal_assembly_vertex *self, int flag) { CORE_DEBUGGER_ASSERT(flag >= BIOSAL_VERTEX_FLAG_START_VALUE); CORE_DEBUGGER_ASSERT(flag <= BIOSAL_VERTEX_FLAG_END_VALUE); CORE_BITMAP_SET_FLAG(self->flags, flag); }
int core_simple_queue_enqueue(struct core_simple_queue *self, void *data) { struct core_simple_queue_item *new_item; /* * Allocate an item and copy the data. */ new_item = core_simple_queue_allocate_item(self); CORE_DEBUGGER_ASSERT(new_item != NULL); CORE_DEBUGGER_ASSERT(new_item->data_ != NULL); CORE_DEBUGGER_ASSERT(new_item->next_ == NULL); core_memory_copy(new_item->data_, data, self->bytes_per_unit_); ++self->size_; /* * The queue is empty. */ if (self->head_ == NULL && self->tail_ == NULL) { self->tail_ = new_item; self->head_ = self->tail_; return 1; } /* * Otherwise, there is at least one element in the queue. */ self->tail_->next_ = new_item; self->tail_ = new_item; return 1; }
int core_dynamic_hash_table_iterator_next(struct core_dynamic_hash_table_iterator *self, void **key, void **value) { if (!core_dynamic_hash_table_iterator_has_next(self)) { return 0; } CORE_DEBUGGER_ASSERT(core_dynamic_hash_table_state(self->list, self->index) == CORE_HASH_TABLE_BUCKET_OCCUPIED); if (key != NULL) { *key = core_dynamic_hash_table_key(self->list, self->index); #ifdef CORE_DEBUGGER_ASSERT CORE_DEBUGGER_ASSERT(*key != NULL); #endif } if (value != NULL) { *value = core_dynamic_hash_table_value(self->list, self->index); #ifdef CORE_DEBUGGER_ASSERT CORE_DEBUGGER_ASSERT(*value != NULL); #endif } self->index++; return 1; }
void thorium_actor_send_then(struct thorium_actor *self, int destination, struct thorium_message *message, thorium_actor_receive_fn_t handler) { CORE_DEBUGGER_ASSERT(destination != THORIUM_ACTOR_NOBODY); CORE_DEBUGGER_ASSERT(NAME() != THORIUM_ACTOR_NOBODY); thorium_actor_send(self, destination, message); int parent_actor = thorium_message_source(message); int parent_message = thorium_message_get_identifier(message); /* */ LOG("XXX ASK... registering message %d:%d", parent_actor, parent_message); /* * Register the information so that the callback is invoked * when the response arrives. * * the key is parent_actor + parent_message and the value is handler. */ thorium_actor_add_action_with_parent(self, parent_actor, parent_message, handler); /* printf("NOT_IMPLEMENTED src %d dst %d msgid %d:%d" "\n", thorium_actor_name(self), destination, parent_actor, parent_message); */ }
int biosal_dna_kmer_get_symbol(struct biosal_dna_kmer *self, int position, int kmer_length, struct biosal_dna_codec *codec) { CORE_DEBUGGER_ASSERT(position >= 0); CORE_DEBUGGER_ASSERT(position < kmer_length); return biosal_dna_codec_get_nucleotide_code(codec, self->encoded_data, position); }
void thorium_worker_pool_assign_worker_to_actor(struct thorium_worker_pool *pool, int name) { int worker_index; #ifdef THORIUM_WORKER_POOL_USE_LEAST_BUSY int score; #endif #ifdef THORIUM_WORKER_POOL_USE_SCRIPT_ROUND_ROBIN int script; struct thorium_actor *actor; #endif /* printf("DEBUG Needs to do actor placement\n"); */ /* assign this actor to the least busy actor */ worker_index = -1; #ifdef THORIUM_WORKER_POOL_USE_LEAST_BUSY worker_index = thorium_balancer_select_worker_least_busy(&pool->scheduler, &score); #elif defined(THORIUM_WORKER_POOL_USE_SCRIPT_ROUND_ROBIN) actor = thorium_node_get_actor_from_name(pool->node, name); /* * Somehow this actor dead a while ago. */ if (actor == NULL) { return; } /* The actor can't be dead if it does not have an initial * placement... */ CORE_DEBUGGER_ASSERT(actor != NULL); script = thorium_actor_script(actor); worker_index = thorium_balancer_select_worker_script_round_robin(&pool->balancer, script); #endif CORE_DEBUGGER_ASSERT(worker_index >= 0); #ifdef THORIUM_WORKER_POOL_DEBUG printf("ASSIGNING %d to %d\n", name, worker_index); #endif thorium_balancer_set_actor_worker(&pool->balancer, name, worker_index); }
/* *This is called from within the actor running inside this worker. */ void thorium_worker_free_message(struct thorium_worker *worker, struct thorium_message *message) { int source_worker; void *buffer; buffer = thorium_message_buffer(message); source_worker = thorium_message_worker(message); if (source_worker == worker->name) { /* This is from the current worker */ core_memory_pool_free(&worker->outbound_message_memory_pool, buffer); #ifdef THORIUM_WORKER_DEBUG_INJECTION ++worker->counter_freed_outbound_buffers_from_self; #endif } else { /* This is from another fellow local worker * or from another BIOSAL node altogether. */ CORE_DEBUGGER_ASSERT(thorium_message_buffer(message) != NULL); thorium_worker_enqueue_message_for_triage(worker, message); } }
int thorium_mpi1_request_test(struct thorium_mpi1_request *self) { MPI_Status status; int flag; int result; int count; flag = 0; result = MPI_Test(&self->request, &flag, &status); if (result != MPI_SUCCESS) { return 0; } if (!flag) { return 0; } result = MPI_Get_count(&status, MPI_BYTE, &count); CORE_DEBUGGER_ASSERT(count >= 0); if (result != MPI_SUCCESS) { return 0; } self->source = status.MPI_SOURCE; self->tag = status.MPI_TAG; self->count = count; return 1; }
void thorium_transport_destroy(struct thorium_transport *self) { /* * Print the report if requested. */ if (core_bitmap_get_bit_uint32_t(&self->flags, FLAG_PROFILE)) { thorium_transport_profiler_print_report(&self->transport_profiler); } thorium_transport_profiler_destroy(&self->transport_profiler); CORE_DEBUGGER_ASSERT(thorium_transport_get_active_request_count(self) == 0); if (self->transport_interface != NULL) { self->transport_interface->destroy(self); core_memory_free(self->concrete_transport, MEMORY_TRANSPORT); self->concrete_transport = NULL; } self->node = NULL; self->rank = -1; self->size = -1; core_timer_destroy(&self->timer); }
int thorium_worker_enqueue_message_for_triage(struct thorium_worker *worker, struct thorium_message *message) { #ifdef THORIUM_WORKER_DEBUG_INJECTION int worker_name; #endif CORE_DEBUGGER_ASSERT(thorium_message_buffer(message) != NULL); if (!core_fast_ring_push_from_producer(&worker->clean_message_ring_for_triage, message)) { #ifdef SHOW_FULL_RING_WARNINGS printf("thorium_worker: Warning: ring is full, clean_message_ring_for_triage action= %x\n", thorium_message_action(message)); #endif core_fast_queue_enqueue(&worker->clean_message_queue_for_triage, message); #ifdef THORIUM_WORKER_DEBUG_INJECTION } else { /* * Update software counters. */ worker_name = thorium_message_worker(message); if (worker_name >= 0) { ++worker->counter_injected_outbound_buffers_other_local_workers; } else { ++worker->counter_injected_inbound_buffers_from_thorium_core; } #endif } return 1; }
void core_fasta_input_init(struct biosal_input_format *input) { char *file; struct core_fasta_input *fasta; uint64_t offset; fasta = (struct core_fasta_input *)biosal_input_format_implementation(input); file = biosal_input_format_file(input); CORE_DEBUGGER_ASSERT(input->operations != NULL); #if 0 printf("DEBUG BEFORE faulty call.\n"); #endif offset = biosal_input_format_start_offset(input); core_buffered_reader_init(&fasta->reader, file, offset); fasta->buffer = NULL; fasta->next_header = NULL; fasta->has_header = 0; fasta->has_first = 0; }
int core_dynamic_hash_table_iterator_has_next(struct core_dynamic_hash_table_iterator *self) { uint64_t size; if (self->list == NULL) { return 0; } size = core_dynamic_hash_table_buckets(self->list); if (size == 0) { return 0; } while (self->index < size && core_dynamic_hash_table_state(self->list, self->index) != CORE_HASH_TABLE_BUCKET_OCCUPIED) { self->index++; } if (self->index >= size) { return 0; } /* Make sure that the pointed bucket is occupied */ CORE_DEBUGGER_ASSERT(core_dynamic_hash_table_state(self->list, self->index) == CORE_HASH_TABLE_BUCKET_OCCUPIED); return 1; }
void thorium_message_init(struct thorium_message *self, int action, int count, void *buffer) { CORE_DEBUGGER_ASSERT(action != THORIUM_MESSAGE_INVALID_ACTION); self->action= action; self->buffer = buffer; self->count = count; self->source_actor = -1; self->destination_actor = -1; /* ranks are set with thorium_node_resolve */ self->source_node = -1; self->destination_node = -1; #ifdef THORIUM_MESSAGE_USE_ROUTING self->routing_source = -1; self->routing_destination = -1; #endif self->worker = -1; thorium_message_set_type(self, THORIUM_MESSAGE_TYPE_NONE); #ifdef THORIUM_MESSAGE_ENABLE_TRACEPOINTS thorium_message_initialize_tracepoints(self); #endif }
/* This can only be called from the PRODUCER */ int thorium_worker_enqueue_actor(struct thorium_worker *worker, struct thorium_actor *actor) { int value; CORE_DEBUGGER_ASSERT(actor != NULL); value = core_fast_ring_push_from_producer(&worker->actors_to_schedule, &actor); #ifdef SHOW_FULL_RING_WARNINGS if (!value) { printf("thorium_worker: Warning: ring is full, actors_to_schedule\n"); } #endif /* * Do a wake up if necessary when scheduling an actor in * the scheduling queue. */ if (value && worker->waiting_is_enabled) { /* * This call checks if the thread is currently waiting. * If it is currently waiting, then a signal is sent * to tell the operating system to wake up the thread so that * it continues its good work for the actor computation in thorium. */ thorium_worker_signal(worker); } return value; }
void biosal_assembly_graph_store_set_vertex_flag(struct thorium_actor *self, struct thorium_message *message) { char *buffer; int count; int flag; struct biosal_dna_kmer transport_kmer; struct biosal_assembly_vertex *vertex; struct biosal_assembly_graph_store *concrete_self; struct core_memory_pool *ephemeral_memory; int position; concrete_self = thorium_actor_concrete_actor(self); ephemeral_memory = thorium_actor_get_ephemeral_memory(self); biosal_dna_kmer_init_empty(&transport_kmer); buffer = thorium_message_buffer(message); count = thorium_message_count(message); position = 0; position += biosal_dna_kmer_unpack(&transport_kmer, buffer, concrete_self->kmer_length, ephemeral_memory, &concrete_self->transport_codec); core_memory_copy(&flag, buffer + position, sizeof(flag)); position += sizeof(flag); CORE_DEBUGGER_ASSERT_IS_EQUAL_INT(position, count); CORE_DEBUGGER_ASSERT(flag >= BIOSAL_VERTEX_FLAG_START_VALUE); CORE_DEBUGGER_ASSERT(flag <= BIOSAL_VERTEX_FLAG_END_VALUE); if (flag == BIOSAL_VERTEX_FLAG_UNITIG) { ++concrete_self->unitig_vertex_count; } #if 0 printf("DEBUG ACTION_SET_VERTEX_FLAG %d\n", flag); #endif vertex = biosal_assembly_graph_store_find_vertex(self, &transport_kmer); CORE_DEBUGGER_ASSERT_NOT_NULL(vertex); biosal_dna_kmer_destroy(&transport_kmer, ephemeral_memory); biosal_assembly_vertex_set_flag(vertex, flag); thorium_actor_send_reply_empty(self, ACTION_SET_VERTEX_FLAG_REPLY); }
void thorium_worker_evict_actor(struct thorium_worker *worker, int actor_name) { struct thorium_actor *actor; int name; struct core_fast_queue saved_actors; int count; int value; core_set_add(&worker->evicted_actors, &actor_name); core_map_delete(&worker->actors, &actor_name); core_fast_queue_init(&saved_actors, sizeof(struct thorium_actor *)); /* evict the actor from the scheduling queue */ while (thorium_scheduler_dequeue(&worker->scheduler, &actor)) { name = thorium_actor_name(actor); if (name != actor_name) { core_fast_queue_enqueue(&saved_actors, &actor); } } while (core_fast_queue_dequeue(&saved_actors, &actor)) { thorium_scheduler_enqueue(&worker->scheduler, actor); } core_fast_queue_destroy(&saved_actors); /* Evict the actor from the ring */ count = core_fast_ring_size_from_consumer(&worker->actors_to_schedule); while (count-- && core_fast_ring_pop_from_consumer(&worker->actors_to_schedule, &actor)) { name = thorium_actor_name(actor); if (name != actor_name) { /* * This can not fail logically. */ value = core_fast_ring_push_from_producer(&worker->actors_to_schedule, &actor); CORE_DEBUGGER_ASSERT(value); } } core_map_iterator_destroy(&worker->actor_iterator); core_map_iterator_init(&worker->actor_iterator, &worker->actors); }
void thorium_actor_send_range_default(struct thorium_actor *actor, struct core_vector *actors, int first, int last, struct thorium_message *message) { int use_binomial_tree; struct core_vector destinations; struct core_memory_pool *ephemeral_memory; int name; int action; action = thorium_message_action(message); use_binomial_tree = 0; #ifdef USE_BINOMIAL_TREE /* * ACTION_ASK_TO_STOP basically kills actors (if they agree to). * It is a bad idea to use a binomial tree to send this death signal * since intermediate actors can die before acting as relays. */ if (action != ACTION_ASK_TO_STOP) use_binomial_tree = 1; #endif if (!use_binomial_tree) { thorium_actor_send_range_loop(actor, actors, first, last, message); return; } tracepoint(thorium_binomial_tree, send_range, message, (int)core_vector_size(actors)); /* * Otherwise, use the binomial tree code path. This algorithm is better since it distributed * the sending operations intot a binomial tree where there are a lot of intermediate * actors (to be exact, the number of intermediate actors is close to log2(actors.size)). */ ephemeral_memory = thorium_actor_get_ephemeral_memory(actor); core_vector_init(&destinations, sizeof(int)); core_vector_set_memory_pool(&destinations, ephemeral_memory); CORE_DEBUGGER_ASSERT(core_vector_empty(&destinations)); core_vector_copy_range(actors, first, last, &destinations); /* * Set the source now. */ name = thorium_actor_name(actor); thorium_message_set_source(message, name); thorium_actor_send_range_binomial_tree(actor, &destinations, message); core_vector_destroy(&destinations); }
void thorium_cfs_scheduler_destroy(struct thorium_scheduler *self) { struct thorium_cfs_scheduler *concrete_self; concrete_self = self->concrete_self; core_red_black_tree_destroy(&concrete_self->tree); CORE_DEBUGGER_ASSERT(core_memory_pool_profile_balance_count(&concrete_self->pool) == 0); core_memory_pool_destroy(&concrete_self->pool); }
void core_dynamic_hash_table_delete(struct core_dynamic_hash_table *self, void *key) { void *bucket; if (!self->resize_in_progress) { core_hash_table_delete(self->current, key); CORE_DEBUGGER_ASSERT(core_dynamic_hash_table_get(self, key) == NULL); return; } /* if the resizing is completed, everything is in current */ if (core_dynamic_hash_table_resize(self)) { core_hash_table_delete(self->current, key); CORE_DEBUGGER_ASSERT(core_dynamic_hash_table_get(self, key) == NULL); return; } /* First look for the key in * the next table */ bucket = core_hash_table_get(self->next, key); if (bucket != NULL) { core_hash_table_delete(self->next, key); CORE_DEBUGGER_ASSERT(core_dynamic_hash_table_get(self, key) == NULL); return; } core_hash_table_delete(self->current, key); CORE_DEBUGGER_ASSERT(core_dynamic_hash_table_get(self, key) == NULL); }
void thorium_multiplexed_buffer_append(struct thorium_multiplexed_buffer *self, int count, void *buffer, uint64_t time) { void *multiplexed_buffer; void *destination_in_buffer; int required_size; ++self->counter_original_message_count; CORE_DEBUGGER_ASSERT(self->buffer_ != NULL); required_size = thorium_multiplexed_buffer_required_size(self, count); /* * Make sure there is enough space. */ CORE_DEBUGGER_ASSERT(self->maximum_size_ - self->current_size_ >= required_size); multiplexed_buffer = self->buffer_; destination_in_buffer = ((char *)multiplexed_buffer) + self->current_size_; /* * Append <count><buffer> to the <multiplexed_buffer> */ core_memory_copy(destination_in_buffer, &count, sizeof(count)); core_memory_copy((char *)destination_in_buffer + sizeof(count), buffer, count); /* * Add the message. */ CORE_DEBUGGER_ASSERT(self->current_size_ <= self->maximum_size_); self->current_size_ += required_size; ++self->message_count_; CORE_DEBUGGER_ASSERT(self->message_count_ >= 1); thorium_multiplexed_buffer_profile(self, time); }
int thorium_worker_dequeue_message_for_triage(struct thorium_worker *worker, struct thorium_message *message) { int value; value = core_fast_ring_pop_from_consumer(&worker->clean_message_ring_for_triage, message); #ifdef CORE_DEBUGGER_ENABLE_ASSERT if (value) { CORE_DEBUGGER_ASSERT(thorium_message_buffer(message) != NULL); } #endif return value; }
void core_string_swap_c_string(char *sequence, int i, int j) { char value; CORE_DEBUGGER_ASSERT(sequence != NULL); value = sequence[i]; sequence[i] = sequence[j]; sequence[j] = value; #ifdef DEBUG_STRING printf("SWAP %d %d result %s\n", i, j, sequence); #endif }
struct biosal_assembly_vertex *biosal_assembly_graph_store_find_vertex(struct thorium_actor *self, struct biosal_dna_kmer *kmer) { struct core_memory_pool *ephemeral_memory; struct biosal_assembly_graph_store *concrete_self; char *sequence; struct biosal_dna_kmer storage_kmer; char *key; struct biosal_assembly_vertex *canonical_vertex; ephemeral_memory = thorium_actor_get_ephemeral_memory(self); concrete_self = thorium_actor_concrete_actor(self); sequence = core_memory_pool_allocate(ephemeral_memory, concrete_self->kmer_length + 1); biosal_dna_kmer_get_sequence(kmer, sequence, concrete_self->kmer_length, &concrete_self->transport_codec); biosal_dna_kmer_init(&storage_kmer, sequence, &concrete_self->storage_codec, ephemeral_memory); key = core_memory_pool_allocate(ephemeral_memory, concrete_self->key_length_in_bytes); biosal_dna_kmer_pack_store_key(&storage_kmer, key, concrete_self->kmer_length, &concrete_self->storage_codec, ephemeral_memory); canonical_vertex = core_map_get(&concrete_self->table, key); #ifdef CORE_DEBUGGER_ASSERT if (canonical_vertex == NULL) { printf("not found Seq = %s name %d kmerlength %d key_length %d hash %" PRIu64 "\n", sequence, thorium_actor_name(self), concrete_self->kmer_length, concrete_self->key_length_in_bytes, biosal_dna_kmer_hash(&storage_kmer, concrete_self->kmer_length, &concrete_self->storage_codec)); } #endif CORE_DEBUGGER_ASSERT(canonical_vertex != NULL); core_memory_pool_free(ephemeral_memory, sequence); core_memory_pool_free(ephemeral_memory, key); biosal_dna_kmer_destroy(&storage_kmer, ephemeral_memory); return canonical_vertex; }
void biosal_assembly_graph_store_mark_as_used(struct thorium_actor *self, struct biosal_assembly_vertex *vertex, int source, int path) { struct biosal_assembly_graph_store *concrete_self; CORE_DEBUGGER_ASSERT(source >= 0); CORE_DEBUGGER_ASSERT(path >= 0); concrete_self = thorium_actor_concrete_actor(self); if (!biosal_assembly_vertex_get_flag(vertex, BIOSAL_VERTEX_FLAG_USED)) { biosal_assembly_vertex_set_flag(vertex, BIOSAL_VERTEX_FLAG_USED); ++concrete_self->consumed_canonical_vertex_count; biosal_assembly_graph_store_print_progress(self); } #if 0 printf("%s set last_actor %d last_path_index %d\n", thorium_actor_script_name(self), source, path); #endif biosal_assembly_vertex_set_last_actor(vertex, source, path); }
int thorium_fifo_scheduler_enqueue(struct thorium_scheduler *self, struct thorium_actor *actor) { int priority; struct core_fast_queue *selected_queue; struct thorium_fifo_scheduler *queue; queue = self->concrete_self; CORE_DEBUGGER_ASSERT(actor != NULL); priority = thorium_actor_get_priority(actor); selected_queue = thorium_fifo_scheduler_select_queue(queue, priority); return core_fast_queue_enqueue(selected_queue, &actor); }
void core_vector_destroy(struct core_vector *self) { if (self->data != NULL) { core_memory_pool_free(self->memory, self->data); ++self->profile_free_calls; self->data = NULL; } CORE_DEBUGGER_ASSERT(self->profile_allocate_calls == self->profile_free_calls); self->element_size = 0; self->maximum_size = 0; self->size = 0; core_vector_set_memory_pool(self, NULL); }
void *core_vector_at(struct core_vector *self, int64_t index) { #if 0 CORE_DEBUGGER_ASSERT(index < self->size); #endif if (index >= self->size) { return NULL; } if (index < 0) { return NULL; } return ((char *)self->data) + index * self->element_size; }
void thorium_actor_unpack_proxy_message(struct thorium_actor *self, struct thorium_message *message) { int new_count; int tag; int source; void *buffer; int offset; buffer = thorium_message_buffer(message); new_count = thorium_message_count(message); new_count -= sizeof(source); new_count -= sizeof(tag); offset = new_count; source = *(int *)((char *)buffer + offset); offset += sizeof(source); tag = *(int *)((char *)buffer + offset); #ifdef DEBUG_BINOMIAL_TREE printf("DEBUG_BINOMIAL_TREE unpack_proxy_message real_count %d real_source %d real_action %x\n", new_count, source, tag); #endif /* * The action can not be ACTION_INVALID because it is invalid * by convention. */ CORE_DEBUGGER_ASSERT(tag != ACTION_INVALID); offset += sizeof(tag); /*thorium_message_init(message, tag, new_count, buffer);*/ /* * Change the tag, source, and count. */ thorium_message_set_source(message, source); thorium_message_set_action(message, tag); thorium_message_set_count(message, new_count); #if 0 printf("DEBUG unpack_proxy_message... source %d tag %d count %d\n", source, tag, new_count); #endif }
void biosal_input_format_init(struct biosal_input_format *input, void *implementation, struct biosal_input_format_interface *operations, char *file, uint64_t start_offset, uint64_t end_offset) { biosal_input_format_interface_init_fn_t handler; FILE *descriptor; #if 0 printf("DEBUG biosal_input_format_init\n"); #endif input->implementation = implementation; CORE_DEBUGGER_ASSERT(operations != NULL); input->operations = operations; input->sequences = 0; input->file = file; input->error = BIOSAL_INPUT_ERROR_NO_ERROR; input->start_offset = start_offset; input->end_offset = end_offset; descriptor = fopen(input->file, "r"); if (descriptor == NULL) { input->error = BIOSAL_INPUT_ERROR_FILE_NOT_FOUND; return; } else { fclose(descriptor); } #if 0 printf("DEBUG INPUT_FORMAT %s from %" PRIu64 " to %" PRIu64 "\n", file, start_offset, end_offset); #endif handler = biosal_input_format_interface_get_init(input->operations); handler(input); #if 0 printf("DEBUG after concrete init\n"); #endif }
/* \see http://www.mpich.org/static/docs/v3.1/www3/MPI_Isend.html */ int thorium_mpi1_pt2pt_transport_send(struct thorium_transport *self, struct thorium_message *message) { struct thorium_mpi1_pt2pt_transport *concrete_self; char *buffer; int count; int destination; int tag; MPI_Request *request; struct thorium_mpi1_pt2pt_active_request active_request; int worker; int result; concrete_self = thorium_transport_get_concrete_transport(self); worker = thorium_message_worker(message); buffer = thorium_message_buffer(message); count = thorium_message_count(message); destination = thorium_message_destination_node(message); tag = DUMMY_TAG; thorium_mpi1_pt2pt_active_request_init(&active_request, buffer, worker); request = thorium_mpi1_pt2pt_active_request_request(&active_request); CORE_DEBUGGER_ASSERT(buffer == NULL || count > 0); /* get return value */ result = MPI_Isend(buffer, count, concrete_self->datatype, destination, tag, concrete_self->comm, request); if (result != MPI_SUCCESS) { return 0; } /* store the MPI_Request to test it later to know when * the buffer can be reused */ /* \see http://blogs.cisco.com/performance/mpi_request_free-is-evil/ */ /*MPI_Request_free(&request);*/ core_fast_queue_enqueue(&concrete_self->active_requests, &active_request); return 1; }