int process(const ecto::tendrils& inputs, const ecto::tendrils& outputs) { boost::asio::io_service s; boost::asio::deadline_timer dt(s); boost::mutex::scoped_try_lock lock(mtx); // try to rock if (lock.owns_lock()) { // we got the rock... i.e. we are rocking ECTO_LOG_DEBUG("%p got the lock.", this); // wait a bit so's we can be sure there will be collisions ecto::test::random_delay(); double value = inputs.get<double> ("in"); ECTO_LOG_DEBUG("nonconcurrent node @ %p moving %f", this % value); // do yer thing outputs.get<double> ("out") = value; // unrock ECTO_LOG_DEBUG("%p done with the lock.", this); } else { std::cout << this << " did NOT get the lock, I'm going to throw about this." << std::endl; BOOST_THROW_EXCEPTION(std::runtime_error("AAAAGH NO LOCK HEEEEEELP")); assert(false && "we should NOT be here"); // throw std::logic_error("Didn't get the lock... this means we were called from two threads. Baaad."); } return ecto::OK; }
int invoke_process(graph_t& graph, graph_t::vertex_descriptor vd) { vertex_ptr v = graph[vd]; cell::ptr m = v->cell(); #if defined(ECTO_LOGGING) const std::string name = m->name(); const std::size_t tick = v->tick(); #endif ECTO_LOG_DEBUG(">> process %s tick %u", name % tick); move_inputs(graph, vd); int rval = ecto::QUIT; { // BEGIN stats_collector scope. profile::stats_collector c(m->name(), v->stats()); rval = m->process(); } // END stats_collector scope. if (rval != ecto::OK) { ECTO_LOG_DEBUG("** process %s tick %u *BAILOUT*", name % tick); return rval; // short circuit. } move_outputs(graph, vd); return rval; }
int invoke_process(graph_t& graph, graph_t::vertex_descriptor vd) { cell::ptr m = graph[vd]; std::size_t tick = m->tick(); ECTO_LOG_DEBUG(">> process %s tick %u", m->name() % tick); if (m->stop_requested()) { ECTO_LOG_DEBUG("%s Not processing because stop_requested", m->name()); return ecto::QUIT; } graph_t::in_edge_iterator inbegin, inend; tie(inbegin, inend) = boost::in_edges(vd, graph); while (inbegin != inend) { edge_ptr e = graph[*inbegin]; tendril& from = e->front(); tendril& to = *(m->inputs[e->to_port()]); ECTO_LOG_DEBUG("Moving inputs to cell %s: tick=%u, from.tick=%u", m->name() % tick % from.tick); ECTO_ASSERT(tick == from.tick, "Internal scheduler error, graph has become somehow desynchronized."); to << from; // ECTO_ASSERT(to.tick == tick, "Graph has become somehow desynchronized"); e->pop_front(); //todo Make this use a pool, instead of popping. To get rid of allocations. ++inbegin; } //verify that all inputs have been set. m->verify_inputs(); int rval; try { rval = m->process(); } catch (...) { m->stop_requested(true); throw; } if(rval != ecto::OK) { ECTO_LOG_DEBUG("** process %s tick %u *BAILOUT*", m->name() % tick); return rval; //short circuit. } graph_t::out_edge_iterator outbegin, outend; tie(outbegin, outend) = boost::out_edges(vd, graph); while (outbegin != outend) { edge_ptr e = graph[*outbegin]; tendril& from = *(m->outputs[e->from_port()]); from.tick = tick; // ECTO_LOG_DEBUG("%s Put output with tick %u", m->name() % from.tick); e->push_back(from);//copy everything... value, docs, user_defined, etc... ++outbegin; } m->inc_tick(); // ECTO_LOG_DEBUG("Incrementing tick on %s to %u", m->name() % m->tick()); ECTO_LOG_DEBUG("<< process %s tick %u", m->name() % tick); return rval; }
int process(const tendrils&, const tendrils&) { ECTO_LOG_DEBUG("<< process DoOverFor, current=%u N=%u", *current % N); ++(*current); if (! (*current % N)) { *out = *in; // Only set outputs when returning OK. ECTO_LOG_DEBUG("<< Returning OK ...", N); return ecto::OK; } return ecto::DO_OVER; }
void move_outputs(graph_t& graph, graph_t::vertex_descriptor vd) { vertex_ptr v = graph[vd]; cell::ptr m = v->cell(); #if defined(ECTO_LOGGING) const std::string name = m->name(); #endif graph_t::out_edge_iterator outbegin, outend; tie(outbegin, outend) = boost::out_edges(vd, graph); while (outbegin != outend) { edge_ptr e = graph[*outbegin]; assert(v->tick() == e->tick()); tendril& from = *(m->outputs[e->from_port()]); ECTO_LOG_DEBUG("%s Put output with tick %u", name % e->tick()); e->push_back(from);//copy everything... value, docs, user_defined, etc... e->inc_tick(); ++outbegin; } v->inc_tick(); ECTO_LOG_DEBUG("<< process %s tick %u", name % v->tick()); }
void move_inputs(graph_t& graph, graph_t::vertex_descriptor vd) { vertex_ptr v = graph[vd]; cell::ptr m = v->cell(); const std::string name = m->name(); #if defined(ECTO_LOGGING) const std::size_t tick = v->tick(); #endif graph_t::in_edge_iterator inbegin, inend; tie(inbegin, inend) = boost::in_edges(vd, graph); for (; inbegin != inend; ++inbegin) { edge_ptr e = graph[*inbegin]; if (e->empty()) { // TODO (JTF): This can be true if a cell requests a DO_OVER, so how do // we validate inputs correctly? continue; } tendril& from = e->front(); tendril& to = *(m->inputs[e->to_port()]); ECTO_LOG_DEBUG("Moving inputs to cell %s: tick=%u, from.tick=%u", name % tick % e->tick()); try { to << from; } catch(const ecto::except::EctoException& ex) { BOOST_THROW_EXCEPTION(except::CellException() << except::type(name_of(typeid(ex))) << except::what(ex.what()) << except::cell_name(name) << except::when(boost::str( boost::format("Copying %s to %s")%e->from_port()%e->to_port()))); throw; } e->pop_front(); // TODO: Make this use a pool instead of popping (to get rid of allocations). } // Verify that all inputs have been set. m->verify_inputs(); }
void cell::set_strand(ecto::strand s) { ECTO_LOG_DEBUG("set_strand id=%p", s.id()); strand_ = s; }
void cell::reset_strand() { ECTO_LOG_DEBUG("reset_strand (%p)", 0); strand_.reset(); }
void cell::stop() { ECTO_LOG_DEBUG("*** %s", "notified of stop"); dispatch_stop(); }
void sample_siggy(cell& c, unsigned firing) { ECTO_LOG_DEBUG("sample_siggy(%s, %u)", c.name() % firing); }
void operator()(Archive& ar, const tendril& t) const { ECTO_LOG_DEBUG("%s", ""); ar << t.get<T>(); }