static void receiver_eval_pending(receiver_t *self, atom_t selector, context_t *context) { message_fifo_t *fifo = get_fifo(self, selector); node_iterator_t it; if (fifo == NULL) { WARNING2("fifo for selector '%s' inexistant.", atom_get_cstring_value(selector)); return; } TRACE2("eval_pending for fifo: '%s'", atom_get_cstring_value(fifo->atom)); if (fifo->end == NULL) { return; } if (get_node_iterator_end(fifo, &it)) { message_node_t *current; while ((current = node_iterator_prev(&it))) { TRACE2("current: %f", current->context->ms); if (!current->dispatched_p) { if (current->context->is_in(current->context, context)) { self->eval(self, current->bytecodes, current->context); current->dispatched_p = 1; } else { break; } } } } }
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 message_node_t *receiver_peek_pending(receiver_t *self, atom_t selector, context_t *context) { message_fifo_t *fifo = get_fifo(self, selector); node_iterator_t it; message_node_t *head = NULL; if (fifo == NULL) { WARNING2("fifo for selector '%s' inexistant.", atom_get_cstring_value(selector)); return NULL; } else if (fifo->end == NULL) { return NULL; } if (get_node_iterator_end(fifo, &it)) { message_node_t *current; while ((current = node_iterator_prev(&it))) { TRACE2("ms: %f.", current->context->ms); if (!current->dispatched_p && current->context->is_in(current->context, context)) { head = current; break; } } } return head; }
static void 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; 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 message_fifo_t *add_fifo(receiver_t *self, atom_t a) { message_fifo_t *fifo = get_fifo(self, a); TRACE2("adding fifo: '%s'\n", atom_get_cstring_value(a)); if (!fifo) { fifo = message_fifo_instantiate_toplevel(NULL); fifo->atom = a; fifo->end = NULL; map_put(&self->fifos, (unsigned long)a, fifo); } return fifo; }
static void router_set_child(router_t* self, atom_t name, receiver_t* child) { router_slot_t* slot = get_slot(self, name); if(child == &self->super) { /* detect stupid errors, but not complicated loops */ WARNING1("what the f**k are you trying to do."); } if(!slot) { slot = calloc(sizeof(router_slot_t), 1); map_put (&self->children, (unsigned long) name, slot); TRACE2("added slot for selector: '%s'", atom_get_cstring_value(name)); } slot->name = name; slot->receiver = child; }
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; } }