/** wait for howlong, for one more message to be available */ public static boolean wait_timeout(EProc proc, EObject howlong) throws Pausable { try { proc.check_exit(); if (ipclog.isLoggable(Level.FINE)) ipclog.fine("WAIT| " + proc + " waits for messages for " + howlong + " ms"); if (howlong == am_infinity) { proc.mbox.untilHasMessages(proc.midx + 1); proc.check_exit(); if (ipclog.isLoggable(Level.FINE)) ipclog.fine("WAIT| " + proc + " wakes up on message"); return true; } else { long now = System.currentTimeMillis(); if (proc.midx == 0 || proc.timeout_start == 0L) { proc.timeout_start = now; } EInteger ei; if ((ei = howlong.testInteger()) == null) throw new ErlangError(EAtom.intern("timeout_value")); long end = proc.timeout_start + ei.longValue(); long left = end - now; if (left < 0) { return false; } if (!proc.in_receive) { Task.sleep(left); return false; } else { if (ipclog.isLoggable(Level.FINE)) ipclog.fine( "WAIT| " + proc + " waiting for " + left + "ms for msg #" + (proc.midx + 1)); boolean res = proc.mbox.untilHasMessages(proc.midx + 1, left); proc.check_exit(); if (ipclog.isLoggable(Level.FINE)) ipclog.fine("WAIT| " + proc + " wakes up " + (res ? "on message" : "after timeout")); return res; } } } finally { proc.in_receive = false; } }
@BIF public static EObject start_timer(EObject time, final EObject rcv, final EObject msg) { // check arguments EInteger when = time.testInteger(); final EInternalPID rcv_pid = rcv.testInternalPID(); EAtom rcv_atom = rcv.testAtom(); if (when == null || gt(when, max_send_time) || lt(when, zero) || (rcv_pid == null && rcv_atom == null)) { throw ERT.badarg(time, rcv, msg); } ETimerTask send_task = new ETimerTask(rcv_pid) { @Override public void on_timeout() throws Pausable { ETuple3 timeout_msg = new ETuple3(); timeout_msg.elem1 = am_timeout; timeout_msg.elem2 = this.ref; timeout_msg.elem3 = msg; EHandle p; if ((p = rcv.testHandle()) != null) { p.sendb(timeout_msg); return; } p = register.get(rcv); if (p != null) { p.sendb(timeout_msg); } } }; send_task.schedule(when.longValue()); return send_task.ref; }
@BIF public static EObject send_after( final EProc proc, EObject time, final EObject rcv, final EObject msg) { // check arguments EInteger when = time.testInteger(); final EInternalPID rcv_pid = rcv.testInternalPID(); EAtom rcv_atom = rcv.testAtom(); if (when == null || gt(when, max_send_time) || lt(when, zero) || (rcv_pid == null && rcv_atom == null)) { throw ERT.badarg(time, rcv, msg); } ETimerTask send_task = new ETimerTask(rcv_pid) { @Override public void on_timeout() throws Pausable { EHandle p; if ((p = rcv.testHandle()) != null) { p.send(proc.self_handle(), msg); return; } p = register.get(rcv); if (p != null) { p.send(proc.self_handle(), msg); } } }; send_task.schedule(when.longValue()); return send_task.ref; }