void worker_scheduleEvent(Event* event, SimulationTime nano_delay, GQuark receiver_node_id) { /* TODO create accessors, or better yet refactor the work to event class */ utility_assert(event); /* get our thread-private worker */ Worker* worker = _worker_getPrivate(); /* when the event will execute */ shadowevent_setTime(event, worker->clock_now + nano_delay); /* parties involved. sender may be NULL, receiver may not! */ Host* sender = worker->cached_node; /* we MAY NOT OWN the receiver, so do not write to it! */ Host* receiver = receiver_node_id == 0 ? sender : _slave_getHost(worker->slave, receiver_node_id); utility_assert(receiver); /* the NodeEvent needs a pointer to the correct node */ shadowevent_setNode(event, receiver); /* if we are not going to execute any more events, free it and return */ if(slave_isKilled(worker->slave)) { shadowevent_free(event); return; } /* engine is not killed, assert accurate worker clock */ utility_assert(worker->clock_now != SIMTIME_INVALID); /* figure out where to push the event */ if(worker->serialEventQueue) { /* single-threaded, push to global serial queue */ eventqueue_push(worker->serialEventQueue, event); } else { /* non-local events must be properly delayed so the event wont show up at another worker * before the next scheduling interval. this is only a problem if the sender and * receivers have been assigned to different workers. */ if(!host_isEqual(receiver, sender)) { SimulationTime jump = slave_getMinTimeJump(worker->slave); SimulationTime minTime = worker->clock_now + jump; /* warn and adjust time if needed */ SimulationTime eventTime = shadowevent_getTime(event); if(eventTime < minTime) { info("Inter-node event time %"G_GUINT64_FORMAT" changed to %"G_GUINT64_FORMAT" due to minimum delay %"G_GUINT64_FORMAT, eventTime, minTime, jump); shadowevent_setTime(event, minTime); } } /* multi-threaded, push event to receiver node */ EventQueue* eventq = host_getEvents(receiver); eventqueue_push(eventq, event); } }
void worker_scheduleEvent(Event* event, SimulationTime nano_delay, GQuark receiver_node_id) { /* TODO create accessors, or better yet refactor the work to event class */ MAGIC_ASSERT(event); MAGIC_ASSERT((&(event->super))); /* get our thread-private worker */ Worker* worker = worker_getPrivate(); Engine* engine = worker->cached_engine; /* when the event will execute */ event->time = worker->clock_now + nano_delay; /* parties involved. sender may be NULL, receiver may not! */ Node* sender = worker->cached_node; /* we MAY NOT OWN the receiver, so do not write to it! */ Node* receiver = receiver_node_id == 0 ? sender : internetwork_getNode(worker_getInternet(), receiver_node_id); g_assert(receiver); /* the NodeEvent needs a pointer to the correct node */ event->node = receiver; /* if we are not going to execute any more events, free it and return */ if(engine_isKilled(engine)) { shadowevent_free(event); return; } /* engine is not killed, assert accurate worker clock */ g_assert(worker->clock_now != SIMTIME_INVALID); /* non-local events must be properly delayed */ SimulationTime jump = engine_getMinTimeJump(engine); if(!node_isEqual(receiver, sender)) { SimulationTime minTime = worker->clock_now + jump; /* warn and adjust time if needed */ if(event->time < minTime) { debug("Inter-node event time %lu changed to %lu due to minimum delay %lu", event->time, minTime, jump); event->time = minTime; } } /* figure out where to push the event */ if(engine_getNumThreads(engine) > 1) { /* multi-threaded, push event to receiver node */ EventQueue* eventq = node_getEvents(receiver); eventqueue_push(eventq, event); } else { /* single-threaded, push to master queue */ engine_pushEvent(engine, (Event*)event); } }