/// <summary> /// AfterFunc waits for the duration to elapse and then calls f in its own goroutine. /// It returns a <see cref="Timer"/> that can be used to cancel the call using its Stop method. /// </summary> public static Timer AfterFunc(TimeSpan duration, Action f) { if (duration < TimeSpan.Zero) { throw new ArgumentOutOfRangeException("duration", duration, "duration must be >= 0"); } if (f == null) { throw new ArgumentNullException("f"); } var timer = new Timer(duration); GoFunc.Run(() => { bool ok; timer.C.ReceiveOk(out ok); if (ok) { f(); } }, string.Format("Time.AfterFunc started:{0} duration:{1}", DateTime.Now, duration)); return(timer); }
/// <summary> /// Creates a new <see cref="Timer"/> that will send the current time on its channel <see cref="C"/> after at least /// <paramref name="duration" />. /// </summary> public Timer(TimeSpan duration) { _isTimerActive = 1; GoFunc.Run(() => { bool ok; Time.After(duration).ReceiveOk(out ok); if (ok) { if (Interlocked.CompareExchange(ref _isTimerActive, 0, 1) == 1) { _timerChan.Send(DateTime.Now); _timerChan.Close(); } } }, string.Format("timer started:{0} duration:{1}", DateTime.Now, duration)); }
/// <summary> /// DialTimeout acts like Dial but takes a timeout. The timeout includes name resolution, if required. /// </summary> public static IConn DialTimeout(string network, string address, TimeSpan timeout) { if (network != "tcp") { throw new ArgumentException("only 'tcp' network is supported", "network"); } var dialChan = new Chan <IConn>(); var timeoutChan = Time.After(timeout); GoFunc.Run(() => { try { var tmpConn = Dial(network, address); dialChan.Send(tmpConn); } catch { // handling timeout below, don't bring down the whole app with an unhandled thread exception } }, "Net:DialTimeout"); IConn conn = null; Select .CaseReceive(dialChan, c => conn = c) .CaseReceive(timeoutChan, o => { throw new TimeoutException(string.Format("timeout {0} exceed when dialing {1}", timeout, address)); }) .NoDefault(); timeoutChan.Close(); return(conn); }