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); }
static void source_send_ping(struct thorium_actor *self) { int target; struct source *concrete_self; concrete_self = thorium_actor_concrete_actor(self); CORE_DEBUGGER_ASSERT(!core_vector_empty(&concrete_self->targets)); if (concrete_self->target == -1) concrete_self->target = thorium_actor_get_random_number(self) % core_vector_size(&concrete_self->targets); target = concrete_self->target; ++concrete_self->target; concrete_self->target %= core_vector_size(&concrete_self->targets); target = core_vector_at_as_int(&concrete_self->targets, target); /* printf("%d sends ACTION_PING to %d\n", thorium_actor_name(self), target); */ thorium_actor_send_empty(self, target, ACTION_PING); }
static void source_receive(struct thorium_actor *self, struct thorium_message *message) { int action; void *buffer; int leader; int source; int count; struct source *concrete_self; int name; concrete_self = (struct source *)thorium_actor_concrete_actor(self); action = thorium_message_action(message); buffer = thorium_message_buffer(message); source = thorium_message_source(message); name = thorium_actor_name(self); count = thorium_message_count(message); if (action == ACTION_ASK_TO_STOP) { thorium_actor_log(self, "sent %d ACTION_PING messages\n", concrete_self->message_count); thorium_actor_send_to_self_empty(self, ACTION_STOP); } else if (action == ACTION_NOTIFY) { #ifdef LATENCY_PROBE_USE_MULTIPLEXER thorium_actor_send_to_self_empty(self, ACTION_ENABLE_MULTIPLEXER); #endif CORE_DEBUGGER_ASSERT(core_vector_empty(&concrete_self->targets)); core_vector_unpack(&concrete_self->targets, buffer); if (source_is_important(self)) { printf("%d (node %d worker %d) has %d targets\n", thorium_actor_name(self), thorium_actor_node_name(self), thorium_actor_worker_name(self), (int)core_vector_size(&concrete_self->targets)); } concrete_self->leader = source; source_send_ping(self); } else if (action == ACTION_PING_REPLY) { CORE_DEBUGGER_ASSERT(count == 0); ++concrete_self->message_count; CORE_DEBUGGER_ASSERT_IS_EQUAL_INT(count, 0); CORE_DEBUGGER_ASSERT_IS_NULL(buffer); if (concrete_self->message_count % PERIOD == 0 || concrete_self->event_count < 500) { if (source_is_important(self)) { printf("progress %d %d/%d\n", name, concrete_self->message_count, concrete_self->event_count); } } if (concrete_self->message_count == concrete_self->event_count) { leader = concrete_self->leader; thorium_actor_send_empty(self, leader, ACTION_NOTIFY_REPLY); if (source_is_important(self)) printf("%d (ACTION_PING sent: %d)" " sends ACTION_NOTIFY_REPLY to %d\n", thorium_actor_name(self), concrete_self->message_count, leader); } else { source_send_ping(self); } } }