public void AlreadySetSignalManuallyAwaitableWithoutExternalCaller() { // here we're simulating the thread-race scenario: // thread A: checks IsCompleted, sees false // thread B: sets the status // thread A: asks for the awaiter and adds a continuation var signal = new Signal(); // A Assert.False(signal.IsCompleted); // B signal.Set(); int wasInvoked = 0; // A signal.OnCompleted(() => { signal.GetResult(); // compiler awaiter always does this Interlocked.Increment(ref wasInvoked); }); Assert.Equal(1, Volatile.Read(ref wasInvoked)); Assert.True(signal.IsCompleted); }
public void SignalDoesNotBecomeCompletedWhenResultFetched() { var signal = new Signal(); signal.Set(); signal.GetResult(); Assert.True(signal.IsCompleted); }
public async Task AlreadySetSignalCompilerAwaitableWithoutExternalCaller() { var signal = new Signal(); signal.Set(); await signal; Assert.True(signal.IsCompleted); signal.Reset(); Assert.False(signal.IsCompleted); }
public async Task SignalCompilerAwaitableWithExternalCaller() { var signal = new Signal(); ThreadPool.QueueUserWorkItem(_ => { Thread.Sleep(100); signal.Set(); }); await signal; Assert.True(signal.IsCompleted); }
public void ResetClearsContinuation() { var signal = new Signal(); bool wasInvoked = false; signal.OnCompleted(() => { signal.GetResult(); wasInvoked = true; }); signal.Reset(); signal.Set(); Assert.False(wasInvoked); }
public void SignalBecomesCompletedWhenSet() { var signal = new Signal(); signal.Set(); Assert.True(signal.IsCompleted); }
public void CallingSetTwiceOnlyInvokesContinuationOnce() { var signal = new Signal(); int count = 0; signal.OnCompleted(() => Interlocked.Increment(ref count)); signal.Set(); signal.GetResult(); signal.Set(); signal.GetResult(); Assert.Equal(1, Volatile.Read(ref count)); }
public void CallingSetTwiceHasNoBacklog() { var signal = new Signal(); signal.Set(); signal.Set(); Assert.True(signal.IsCompleted); signal.GetResult(); Assert.True(signal.IsCompleted); signal.Reset(); Assert.False(signal.IsCompleted); // only set "once" }