/*--- receiver ---*/ static void receiver_eval(receiver_t *self, bytecode_stream_t *message, context_t *context) { self->dispatcher.dispatch(&self->dispatcher, context, message); bytecode_stream_retire(message); context_retire(context); }
static void wildcard_router_receive(receiver_t* self, bytecode_stream_t* message, context_t* context) { router_t* router = (router_t*) self; bytecode_t* selector = message->pop(message); if(selector && selector->verb == route_atom) { bytecode_t* destination = message->pop(message); if(!destination) { WARNING1("no destination provided."); return; } else { atom_t dest = destination->verb; TRACE2("routing towards selector '%s' requested.", atom_get_cstring_value(dest)); if(dest == star_atom) { map_iterator_t i; map_value_t pslot = NULL_MAP_VALUE; map_get_iterator(&router->children, &i); while (map_value_is_there (pslot = map_iterator_next(&i))) { router_slot_t* slot = map_value_obtain (pslot); // clone each message bytecode_stream_t* message_copy = bytecode_stream_instantiate_toplevel(NULL); message_copy->copy(message_copy, message); TRACE2("sending event to slot: '%s'", atom_get_cstring_value(slot->name)); if(!router_route(slot, message_copy, context)) { WARNING2("route '%s' not defined.", atom_get_cstring_value(slot->name)); } } map_iterator_destroy (&i); map_iterator_retire (&i); bytecode_stream_retire (message); } else { if(!router_route(get_slot(router, dest), message, context)) { WARNING2("route '%s' not defined.", atom_get_cstring_value(dest)); } } } } else { message->push(message, selector); router->receive_backup(self, message, context); } }
static void receiver_receive(receiver_t *self, bytecode_stream_t *message, context_t *context) { atom_t selector; message_fifo_t *fifo; message_node_t *node; node_iterator_t it; if (!message || !message->end) { WARNING1("message === NULL"); return; } selector = message->end->code.verb; fifo = get_fifo(self, selector); node = calloc(sizeof(message_node_t), 1); if (!fifo) fifo = add_fifo(self, selector); if (fifo->closed_p) { /* destroy the message and the context objects */ bytecode_stream_retire(message); context_retire(context); return; } /* insert message in the right position messages are ordered by decreasing context from beginning to end. */ if (get_node_iterator(fifo, &it)) { message_node_t *current = NULL; message_node_t *last = NULL; TRACE3("adding at: %f in fifo: %s", context->ms, atom_get_cstring_value(fifo->atom)); while ((current = node_iterator_next(&it)) && context->is_in(context, current->context)) { /* advance until context is not anymore in current context */ TRACE2("current at: %f", current->context->ms); last = current; } if (last == NULL) { if (fifo->end == NULL) { TRACE1("append to empty fifo"); node->next = node; node->prev = node; fifo->end = node; } else { if (context->is_in(context, current->context)) { TRACE2("insert after current at %f", current->context->ms); node->prev = current; node->next = current->next; current->next = node; node->next->prev = node; } else { TRACE2("insert before current at %f", current->context->ms); node->next = current; node->prev = current->prev; current->prev = node; node->prev->next = node; } if (current == fifo->end) fifo->end = node; } } else { if (context->is_in(context, last->context)) { TRACE2("insert after last at %f", last->context->ms); node->prev = last; node->next = last->next; last->next = node; node->next->prev = node; } else { TRACE2("insert before last at %f", last->context->ms); node->next = last; node->prev = last->prev; last->prev = node; node->prev->next = node; } if (last == fifo->end) fifo->end = node; } } node->bytecodes = message; node->context = context; node->dispatched_p = 0; if (node->context->dispatch_now_p) { self->eval(self, node->bytecodes, node->context); node->dispatched_p = 1; } }