T readFF(GlobalAddress<FullEmpty<T>> fe_addr) { if (fe_addr.core() == mycore()) { DVLOG(2) << "local"; return fe_addr.pointer()->readFF(); } FullEmpty<T> result; auto result_addr = make_global(&result); send_message(fe_addr.core(), [fe_addr,result_addr]{ auto& fe = *fe_addr.pointer(); if (fe.full()) { // DVLOG(2) << "no need to block"; fill_remote(result_addr, fe.readFF()); return; } DVLOG(2) << "setting up to block (" << fe_addr << ")"; auto* c = SuspendedDelegate::create([&fe,result_addr]{ VLOG(0) << "suspended_delegate!"; fill_remote(result_addr, fe.readFF()); }); add_waiter(&fe, c); }); return result.readFF(); }
void call_async(Core dest, F func) { static_assert(std::is_same<R, decltype(func())>::value, "return type of callable must match the type of this Promise"); _result.reset(); delegate_ops++; delegate_async_ops++; Core origin = Grappa::mycore(); if (dest == origin) { // short-circuit if local delegate_targets++; delegate_short_circuits++; fill(func()); } else { start_time = Grappa::timestamp(); send_heap_message(dest, [origin, func, this] { delegate_targets++; R val = func(); // TODO: replace with handler-safe send_message send_heap_message(origin, [val, this] { this->network_time = Grappa::timestamp(); Grappa::impl::record_network_latency(this->start_time); this->fill(val); }); }); // send message } }
/// Block on result being returned. inline const R get() { // ... and wait for the result const R r = _result.readFF(); Grappa::impl::record_wakeup_latency(start_time, network_time); return r; }
inline void fill(const R& r) { _result.writeXF(r); }