public void DynamicThreadPoolPerformBalancing() { using (DynamicThreadPool testInst = new DynamicThreadPool(0, 4 * Environment.ProcessorCount, 1000, "name")) { Assert.AreEqual(0, testInst.ActiveThreadCount); // ========== Проверяем, что число потоков увеличивается автоматически от нуля =========== int executedTaskCount = 0; for (int i = 0; i < 1000; i++) { testInst.Run(() => { Interlocked.Increment(ref executedTaskCount); }); } TimingAssert.AreEqual(5000, 1000, () => Volatile.Read(ref executedTaskCount)); Assert.IsTrue(testInst.ActiveThreadCount > 0, "1. testInst.ActiveThreadCount > 0"); // ======== Проверяем, что на большом числе задач он рано или поздно дойдёт до числа потоков равного числу ядер =========== executedTaskCount = 0; for (int i = 0; i < testInst.MaxThreadCount * testInst.QueueCapacity; i++) { testInst.Run(() => { Thread.Sleep(1); Interlocked.Increment(ref executedTaskCount); }); } TimingAssert.AreEqual(15000, testInst.MaxThreadCount * testInst.QueueCapacity, () => Volatile.Read(ref executedTaskCount)); Assert.IsTrue(testInst.ActiveThreadCount >= Environment.ProcessorCount, "2. testInst.ActiveThreadCount >= Environment.ProcessorCount"); // ======== Проверяем, что на долгих задачах число потоков может стать больше числа ядер =========== executedTaskCount = 0; for (int i = 0; i < 1000; i++) { testInst.Run(() => { Thread.Sleep(20); Interlocked.Increment(ref executedTaskCount); }); } TimingAssert.IsTrue(30000, () => Volatile.Read(ref executedTaskCount) >= 500); Assert.IsTrue(testInst.ActiveThreadCount > Environment.ProcessorCount, "3. testInst.ActiveThreadCount > Environment.ProcessorCount"); Assert.IsTrue(testInst.ActiveThreadCount <= testInst.MaxThreadCount, "3. testInst.ActiveThreadCount <= testInst.MaxThreadCount"); TimingAssert.AreEqual(30000, 1000, () => Volatile.Read(ref executedTaskCount)); TimingAssert.IsTrue(5000, () => testInst.ActiveThreadCount <= Environment.ProcessorCount, "4. testInst.ActiveThreadCount <= Environment.ProcessorCount"); } }
internal void DiscoverInterpreterFactories() { if (Volatile.Read(ref _ignoreNotifications) > 0) { return; } // Discover the available interpreters... bool anyChanged = false; PythonRegistrySearch search = null; Dictionary <string, PythonInterpreterInformation> machineFactories = null; try { search = new PythonRegistrySearch(); using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default)) using (var root = baseKey.OpenSubKey(PythonPath)) { search.Search( root, Environment.Is64BitOperatingSystem ? InterpreterArchitecture.Unknown : InterpreterArchitecture.x86 ); } machineFactories = new Dictionary <string, PythonInterpreterInformation>(); using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) using (var root = baseKey.OpenSubKey(PythonPath)) { search.Search( root, InterpreterArchitecture.x86 ); } if (Environment.Is64BitOperatingSystem) { using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)) using (var root = baseKey.OpenSubKey(PythonPath)) { search.Search( root, InterpreterArchitecture.x64 ); } } } catch (ObjectDisposedException) { // We are aborting, so silently return with no results. return; } var found = search.Interpreters .Where(i => !ExcludedVersions.Contains(i.Configuration.Version)) .ToList(); var uniqueIds = new HashSet <string>(found.Select(i => i.Configuration.Id)); // Then update our cached state with the lock held. lock (this) { foreach (var info in found) { PythonInterpreterInformation existingInfo; if (!_factories.TryGetValue(info.Configuration.Id, out existingInfo) || info.Configuration != existingInfo.Configuration) { _factories[info.Configuration.Id] = info; anyChanged = true; } } // Remove any factories we had before and no longer see... foreach (var unregistered in _factories.Keys.Except(uniqueIds).ToArray()) { _factories.Remove(unregistered); anyChanged = true; } } if (anyChanged) { OnInterpreterFactoriesChanged(); } }
public bool Get() => Volatile.Read(ref this.underlying) != 0;
/// <summary> /// Get the current value of this instance /// </summary> /// <returns>The current value of the instance</returns> public double GetValue() { return(Volatile.Read(ref _value)); }
private static void ReprepareTest(bool useKeyspace) { const string keyspace = TestClusterManager.DefaultKeyspaceName; var testCluster = TestClusterManager.CreateNew(); using (var cluster = Cluster.Builder().AddContactPoint(testCluster.InitialContactPoint) .WithPoolingOptions(new PoolingOptions().SetHeartBeatInterval(2000)) .WithReconnectionPolicy(new ConstantReconnectionPolicy(1000)).Build()) { var session = cluster.Connect(); var fqKeyspaceName = ""; session.CreateKeyspaceIfNotExists(keyspace); if (useKeyspace) { session.ChangeKeyspace(keyspace); } else { fqKeyspaceName = keyspace + "."; } try { session.Execute("CREATE TABLE " + fqKeyspaceName + "test(k text PRIMARY KEY, i int)"); } catch (AlreadyExistsException) { } session.Execute("INSERT INTO " + fqKeyspaceName + "test (k, i) VALUES ('123', 17)"); session.Execute("INSERT INTO " + fqKeyspaceName + "test (k, i) VALUES ('124', 18)"); var ps = session.Prepare("SELECT * FROM " + fqKeyspaceName + "test WHERE k = ?"); var rs = session.Execute(ps.Bind("123")); Assert.AreEqual(rs.First().GetValue <int>("i"), 17); var downCounter = 0; var upCounter = 0; var host = cluster.AllHosts().First(); host.Down += _ => { Interlocked.Increment(ref downCounter); }; host.Up += h => { Interlocked.Increment(ref upCounter); }; testCluster.Stop(1); Thread.Sleep(8000); Assert.AreEqual(1, Volatile.Read(ref downCounter), "Should have raised Host.Down once"); Assert.AreEqual(0, Volatile.Read(ref upCounter), "Should not have raised Host.Up"); testCluster.Start(1); Thread.Sleep(8000); TestHelper.WaitUntil(() => Volatile.Read(ref upCounter) == 1, 1000, 20); Assert.AreEqual(1, Volatile.Read(ref downCounter), "Should have raised Host.Down once"); Assert.AreEqual(1, Volatile.Read(ref upCounter), "Should have raised Host.Up once"); Assert.True(session.Cluster.AllHosts().Select(h => h.IsUp).Any(), "There should be one node up"); for (var i = 0; i < 10; i++) { var rowset = session.Execute(ps.Bind("124")); Assert.AreEqual(rowset.First().GetValue <int>("i"), 18); } } }
protected async Task <CommandProcessorThread> EnsureConnectedAsync() { var thread = Volatile.Read(ref _thread); if (thread != null) { return(thread); } return(await _serviceProvider.GetUIThread().InvokeTask(async() => { if (!string.IsNullOrEmpty(ProjectMoniker)) { try { UpdatePropertiesFromProjectMoniker(); } catch (NoInterpretersException ex) { WriteError(ex.ToString()); return null; } catch (MissingInterpreterException ex) { WriteError(ex.ToString()); return null; } catch (DirectoryNotFoundException ex) { WriteError(ex.ToString()); return null; } catch (Exception ex) when(!ex.IsCriticalException()) { WriteError(ex.ToUnhandledExceptionMessage(GetType())); return null; } } var scriptsPath = ScriptsPath; if (!Directory.Exists(scriptsPath) && Configuration != null) { scriptsPath = GetScriptsPath(_serviceProvider, DisplayName, Configuration.Interpreter); } if (!string.IsNullOrEmpty(scriptsPath)) { var modeFile = PathUtils.GetAbsoluteFilePath(scriptsPath, "mode.txt"); if (File.Exists(modeFile)) { try { BackendName = File.ReadAllLines(modeFile).FirstOrDefault(line => !string.IsNullOrEmpty(line) && !line.TrimStart().StartsWith("#") ); } catch (Exception ex) when(!ex.IsCriticalException()) { WriteError(Strings.ReplCannotReadFile.FormatUI(modeFile)); } } else { BackendName = null; } } thread = Connect(); var newerThread = Interlocked.CompareExchange(ref _thread, thread, null); if (newerThread != null) { thread.Dispose(); return newerThread; } await ExecuteStartupScripts(scriptsPath); thread.AvailableScopesChanged += Thread_AvailableScopesChanged; return thread; })); }
private void RunLocalThreadQueuePrimaryScenario(ThreadPoolLocalQueue q, int elemCount, int slealThCount, int fillFactor) { int trackElemCount = elemCount; int addFinished = 0; int atomicRandom = 0; Thread mainThread = null; Thread[] stealThreads = new Thread[slealThCount]; List <int> global = new List <int>(elemCount + 1); Action mainAction = () => { List <int> data = new List <int>(elemCount); Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * slealThCount); while (Volatile.Read(ref trackElemCount) >= 0) { int addCount = fillFactor; if (rnd != null) { addCount = rnd.Next(fillFactor); } for (int i = 0; i < addCount; i++) { int item = --trackElemCount; if (item < 0) { break; } if (!q.TryAddLocal(new TestThreadPoolItem(item))) { ++trackElemCount; break; } } int removeCount = rnd.Next(fillFactor); for (int i = 0; i < removeCount; i++) { ThreadPoolWorkItem item = null; if (!q.TryTakeLocal(out item)) { break; } data.Add((TestThreadPoolItem)item); } } Interlocked.Increment(ref addFinished); ThreadPoolWorkItem finalItem = null; while (q.TryTakeLocal(out finalItem)) { data.Add((TestThreadPoolItem)finalItem); } lock (global) global.AddRange(data); }; Action stealAction = () => { Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * slealThCount); List <int> data = new List <int>(); while (Volatile.Read(ref addFinished) < 1 && Volatile.Read(ref trackElemCount) > elemCount / 1000) { ThreadPoolWorkItem tmp; if (q.TrySteal(out tmp)) { data.Add((TestThreadPoolItem)tmp); } int sleepTime = rnd.Next(5) - 3; if (sleepTime > 0) { Thread.Sleep(sleepTime); } } lock (global) global.AddRange(data); }; mainThread = new Thread(new ThreadStart(mainAction)); for (int i = 0; i < stealThreads.Length; i++) { stealThreads[i] = new Thread(new ThreadStart(stealAction)); } mainThread.Start(); for (int i = 0; i < stealThreads.Length; i++) { stealThreads[i].Start(); } mainThread.Join(); for (int i = 0; i < stealThreads.Length; i++) { stealThreads[i].Join(); } Assert.AreEqual(elemCount, global.Count, "Incorrect element count"); global.Sort(); for (int i = 0; i < elemCount; i++) { Assert.AreEqual(i, global[i], "Incorrect data"); } }
bool TryGet(out TaskCompletionSource <TValue> tcs) { tcs = Volatile.Read <TaskCompletionSource <TValue> >(ref this.taskCompletionSource); return(tcs != null); }
public void TestHardStopWork() { int processed = 0; int startedTask = 0; ManualResetEventSlim waiter = new ManualResetEventSlim(false); using (DelegateQueueAsyncProcessor <int> proc = new DelegateQueueAsyncProcessor <int>(Environment.ProcessorCount, 1000, "name", (elem, token) => { try { Interlocked.Increment(ref startedTask); waiter.Wait(token); } finally { Interlocked.Increment(ref processed); } })) { proc.Start(); for (int i = 0; i < 5 * Environment.ProcessorCount; i++) { proc.Add(i); } Assert.IsTrue(proc.ThreadCount > 0, "proc.ThreadCount > 0"); Assert.IsTrue(proc.ThreadCount == Environment.ProcessorCount, "proc.ThreadCount == Environment.ProcessorCount"); TimingAssert.IsTrue(10000, () => proc.ActiveThreadCount >= 0, "FAILED: wait while thread activated"); TimingAssert.IsTrue(10000, () => proc.ActiveThreadCount == proc.ThreadCount, "FAILED: wait while all threads activated"); TimingAssert.IsTrue(10000, () => Volatile.Read(ref startedTask) >= 0, "FAILED: wait while first thread blocked"); TimingAssert.IsTrue(10000, () => Volatile.Read(ref startedTask) == proc.ThreadCount, () => "FAILED: wait while all thread blocked. Currently blocked = " + Volatile.Read(ref startedTask).ToString() + ", expected = " + proc.ThreadCount.ToString()); proc.Stop(true, false, true); Assert.IsTrue(proc.State == QueueAsyncProcessorState.Stopped, "proc.State == QueueAsyncProcessorState.Stopped"); Assert.IsTrue(processed > 0, "processed > 0"); } }
public static void Raise(this EventHandler handler, object sender, EventArgs e) { Volatile.Read(ref handler)?.Invoke(sender, e); }
public static void Raise <T>(this EventHandler <T> handler, object sender, T e) where T : EventArgs { Volatile.Read(ref handler)?.Invoke(sender, e); }
private void Drain() { if (Interlocked.Increment(ref _trampoline) != 1) { return; } for (; ;) { if (Volatile.Read(ref _isDisposed)) { while (_stack.Count != 0) { var enumerator = _stack.Pop(); enumerator.Dispose(); } Disposable.TryDispose(ref _currentSubscription); } else { if (_stack.Count != 0) { var currentEnumerator = _stack.Peek(); var currentObservable = default(IObservable <TSource>); var next = default(IObservable <TSource>); try { if (currentEnumerator.MoveNext()) { currentObservable = currentEnumerator.Current; } } catch (Exception ex) { currentEnumerator.Dispose(); ForwardOnError(ex); Volatile.Write(ref _isDisposed, true); continue; } try { next = Helpers.Unpack(currentObservable); } catch (Exception ex) { next = null; if (!Fail(ex)) { Volatile.Write(ref _isDisposed, true); } continue; } if (next != null) { var nextSeq = Extract(next); if (nextSeq != null) { if (TryGetEnumerator(nextSeq, out var nextEnumerator)) { _stack.Push(nextEnumerator); continue; } Volatile.Write(ref _isDisposed, true); continue; } // we need an unique indicator for this as // Subscribe could return a Disposable.Empty or // a BooleanDisposable var sad = ReadyToken.Ready; // Swap in the Ready indicator so we know the sequence hasn't been disposed if (Disposable.TrySetSingle(ref _currentSubscription, sad) == TrySetSingleResult.Success) { // subscribe to the source var d = next.SubscribeSafe(this); // Try to swap in the returned disposable in place of the Ready indicator // Since this drain loop is the only one to use Ready, this should // be unambiguous var u = Interlocked.CompareExchange(ref _currentSubscription, d, sad); // sequence disposed or completed synchronously if (u != sad) { d.Dispose(); if (u == BooleanDisposable.True) { continue; } } } else { continue; } } else { _stack.Pop(); currentEnumerator.Dispose(); continue; } } else { Volatile.Write(ref _isDisposed, true); Done(); } } if (Interlocked.Decrement(ref _trampoline) == 0) { break; } } }
private static void AddStat(IDictionary <string, long> stats, string key, ref long value, Func <long, long> converter = null) { stats[I($"DropDaemon.{key}")] = converter != null?converter(Volatile.Read(ref value)) : Volatile.Read(ref value); }
internal void Run() { Thread.CurrentThread.IsBackground = daemon; var n = name; if (n != null) { Thread.CurrentThread.Name = n; } var sh = ShutdownAction; var q = queue; long missed = 0L; for (;;) { if (Volatile.Read(ref shutdown) != 0) { q.Clear(); break; } Action a = null; for (int i = 0; i < 64; i++) { if (q.Poll(out a)) { break; } } if (a != null) { if (a == sh) { q.Clear(); break; } try { a(); } catch { // TODO what to do with these? } } else { long w = Volatile.Read(ref wip); if (w == missed) { missed = Interlocked.Add(ref wip, -missed); if (missed == 0) { if (Monitor.TryEnter(this)) { try { while ((missed = Volatile.Read(ref wip)) == 0) { Monitor.Wait(this); } } finally { Monitor.Exit(this); } } } } else { missed = w; } } } }
/// <summary> /// Retrieves the job object associated with this process, if any. /// </summary> /// <remarks> /// This method can only be invoked after the process has started. /// </remarks> /// <returns> /// Result is null after this instance has been disposed, or if the OS doesn't supported monitoring nested /// processes in jobs. /// </returns> public JobObject GetJobObject() { Contract.Requires(HasStarted); return(Volatile.Read(ref m_job)); }
internal override void Drain() { if (Interlocked.Increment(ref wip) != 1) { return; } var missed = 1; var observers = this.observers; var downstream = this.downstream; var delayErrors = this.delayErrors; var sources = this.queue; for (; ;) { if (Volatile.Read(ref disposed)) { while (observers.TryDequeue(out var inner)) { inner.Dispose(); } while (sources.TryDequeue(out var _)) { ; } } else { if (!delayErrors) { var ex = Volatile.Read(ref errors); if (ex != null) { Volatile.Write(ref disposed, true); downstream.OnError(ex); DisposableHelper.Dispose(ref upstream); continue; } } if (!noMoreSources && active < maxConcurrency && !sources.IsEmpty) { if (sources.TryDequeue(out var v)) { var src = default(ISingleSource <R>); try { src = RequireNonNullRef(mapper(v), "The mapper returned a null ISingleSource"); } catch (Exception ex) { if (delayErrors) { ExceptionHelper.AddException(ref errors, ex); Volatile.Write(ref done, true); } else { Interlocked.CompareExchange(ref errors, ex, null); } noMoreSources = true; DisposableHelper.Dispose(ref upstream); continue; } active++; SubscribeTo(src); continue; } } var d = Volatile.Read(ref done) && sources.IsEmpty; var empty = !observers.TryPeek(out var inner); if (d && empty) { Volatile.Write(ref disposed, true); var ex = Volatile.Read(ref errors); if (ex != null) { downstream.OnError(ex); } else { downstream.OnCompleted(); } DisposableHelper.Dispose(ref upstream); } else if (!empty) { var state = inner.GetState(); if (state == 1) { downstream.OnNext(inner.value); observers.TryDequeue(out var _); active--; continue; } else if (state == 2) { observers.TryDequeue(out var _); active--; continue; } } } missed = Interlocked.Add(ref wip, -missed); if (missed == 0) { break; } } }
/// <summary> /// Retrieves the process id associated with this process. /// </summary> /// <remarks> /// This method can only be invoked after the process has started. /// </remarks> public int GetProcessId() { Contract.Requires(HasStarted); return(Volatile.Read(ref m_processId)); }
internal int CurrentStatus() { return(Volatile.Read(ref _statusDotNotCallMeDirectly)); }
public async Task Session_With_Host_Changing_Distance() { if (TestHelper.IsMono) { Assert.Ignore("The test should not run under the Mono runtime"); } var lbp = new DistanceChangingLbp(); var builder = Cluster.Builder() .AddContactPoint(TestCluster.InitialContactPoint) .WithLoadBalancingPolicy(lbp) .WithPoolingOptions(new PoolingOptions().SetCoreConnectionsPerHost(HostDistance.Local, 3)); var counter = 0; using (var localCluster = builder.Build()) { var localSession = (Session)localCluster.Connect(); var remoteHost = localCluster.AllHosts().First(h => TestHelper.GetLastAddressByte(h) == 2); var stopWatch = new Stopwatch(); var distanceReset = 0; TestHelper.Invoke(() => Session.Execute("SELECT key FROM system.local"), 10); var hosts = localCluster.AllHosts().ToArray(); var pool1 = localSession.GetOrCreateConnectionPool(hosts[0], HostDistance.Local); var pool2 = localSession.GetOrCreateConnectionPool(hosts[1], HostDistance.Local); var tcs = new TaskCompletionSource <RowSet>(); tcs.SetResult(null); var completedTask = tcs.Task; Func <Task <RowSet> > execute = () => { var wasReset = Volatile.Read(ref distanceReset); var count = Interlocked.Increment(ref counter); if (count == 80) { Trace.TraceInformation("Setting to remote: {0}", DateTimeOffset.Now); lbp.SetRemoteHost(remoteHost); stopWatch.Start(); } if (wasReset == 0 && count >= 240 && stopWatch.ElapsedMilliseconds > 2000) { if (Interlocked.CompareExchange(ref distanceReset, 1, 0) == 0) { Trace.TraceInformation("Setting back to local: {0}", DateTimeOffset.Now); lbp.SetRemoteHost(null); stopWatch.Restart(); } } var poolHasBeenReset = wasReset == 1 && pool2.OpenConnections == 3 && stopWatch.ElapsedMilliseconds > 2000; if (poolHasBeenReset) { // We have been setting the host as ignored and then take it back into account // The pool is looking good, there is no point in continue executing queries return(completedTask); } return(localSession.ExecuteAsync(new SimpleStatement("SELECT key FROM system.local"))); }; await TestHelper.TimesLimit(execute, 200000, 32); Assert.That(pool1.OpenConnections, Is.EqualTo(3)); Assert.That(pool2.OpenConnections, Is.EqualTo(3)); } }
bool IsDisposed() { return(Volatile.Read(ref upstream) == DisposableHelper.DISPOSED); }
/// <inheritdoc/> public override IChangeToken GetChangeToken() => Volatile.Read(ref _changeToken);
private NodeValue FindNodeValue(byte[] key, out Node closestNode, out NodeValue closestDelegation, out NodeValue closestAuthority) { closestNode = _root; closestDelegation = null; closestAuthority = null; Node wildcard = null; int i = 0; while (i <= key.Length) { //find authority zone NodeValue value = closestNode.Value; if (value != null) { T zoneValue = value.Value; if (zoneValue != null) { if (zoneValue is AuthZone) { if ((zoneValue is PrimaryZone) || (zoneValue is SecondaryZone) || (zoneValue is StubZone) || (zoneValue is ForwarderZone)) { if (IsKeySubDomain(value.Key, key)) { //hosted primary/secondary/stub/forwarder zone found closestDelegation = null; closestAuthority = value; } } else if ((zoneValue is SubDomainZone) && (closestDelegation == null) && zoneValue.ContainsNameServerRecords()) { if (IsKeySubDomain(value.Key, key)) { //delegated sub domain found closestDelegation = value; } } } else if ((zoneValue is CacheZone) && zoneValue.ContainsNameServerRecords()) { if (IsKeySubDomain(value.Key, key)) { closestDelegation = value; } } } } if (i == key.Length) { break; } Node[] children = closestNode.Children; if (children == null) { break; } Node child = Volatile.Read(ref children[38]); //[*] if (child != null) { wildcard = child; } child = Volatile.Read(ref children[key[i]]); if (child == null) { //no child found if (wildcard == null) { return(null); //no child or wildcard found } //use wildcard node //skip to next label do { i++; if (key[i] == 39) //[.] { break; } }while (i < key.Length); closestNode = wildcard; wildcard = null; continue; } closestNode = child; i++; } { NodeValue value = closestNode.Value; if (value != null) { //match exact + wildcard keys if (KeysMatch(key, value.Key)) { return(value); //found matching value } } } if (wildcard != null) { //wildcard node found NodeValue value = wildcard.Value; if (value == null) { //find value from next [.] node Node[] children = wildcard.Children; if (children != null) { Node child = Volatile.Read(ref children[39]); //[.] if (child != null) { value = child.Value; if (value != null) { //match wildcard keys if (KeysMatch(key, value.Key)) { return(value); //found matching wildcard value } } } } } else { //match wildcard keys if (KeysMatch(key, value.Key)) { return(value); //found matching wildcard value } } } //value not found return(null); }
void Drain() { if (Interlocked.Increment(ref wip) == 1) { var q = queue; for (; ;) { if (Volatile.Read(ref disposed)) { while (q.TryDequeue(out var _)) { ; } } else { if (!active) { if (!delayErrors) { var ex = Volatile.Read(ref errors); if (ex != null) { downstream.OnError(ex); Volatile.Write(ref disposed, true); DisposableHelper.Dispose(ref upstream); continue; } } var d = Volatile.Read(ref done); var empty = !q.TryDequeue(out var v); if (d && empty) { var ex = Volatile.Read(ref errors); if (ex != null) { downstream.OnError(ex); } else { downstream.OnCompleted(); } Volatile.Write(ref disposed, true); DisposableHelper.Dispose(ref upstream); continue; } else if (!empty) { var src = default(IMaybeSource <R>); try { src = RequireNonNullRef(mapper(v), "The mapper returned a null IMaybeSource"); } catch (Exception ex) { DisposableHelper.Dispose(ref upstream); if (delayErrors) { ExceptionHelper.AddException(ref errors, ex); } else { Interlocked.CompareExchange(ref errors, ex, null); } Volatile.Write(ref done, true); continue; } active = true; src.Subscribe(inner); } } } if (Interlocked.Decrement(ref wip) == 0) { break; } } } }
private void Drain() { var q = _queue; for (; ;) { // If the sequence was disposed, clear the queue and quit if (Volatile.Read(ref _disposed)) { while (q.TryDequeue(out var _)) { ; } break; } // Has the upstream terminated? var isDone = Volatile.Read(ref _done); // Do we have an item in the queue var hasValue = q.TryDequeue(out var item); // If the upstream has terminated and no further items are in the queue if (isDone && !hasValue) { // Find out if the upstream terminated with an error and signal accordingly. var e = _error; if (e != null) { ForwardOnError(e); } else { ForwardOnCompleted(); } break; } // There was an item, signal it. if (hasValue) { ForwardOnNext(item); // Consume the item and try the next item if the work-in-progress // indicator is still not zero if (Interlocked.Decrement(ref _wip) != 0L) { continue; } } // If we run out of work and the sequence is not disposed if (Volatile.Read(ref _wip) == 0L && !Volatile.Read(ref _disposed)) { var g = _suspendGuard; // try sleeping, if we can't even enter the lock, the producer // side is currently trying to resume us if (Monitor.TryEnter(g)) { // Make sure again there is still no work and the sequence is not disposed if (Volatile.Read(ref _wip) == 0L && !Volatile.Read(ref _disposed)) { // wait for a Pulse(g) Monitor.Wait(g); } // Unlock Monitor.Exit(g); } } } }
internal bool TryStart(TaskScheduler scheduler, bool inline) { return(Volatile.Read(ref _isDisposed) != 1 && InternalStart(scheduler, inline, true)); }
internal void Drain() { if (!QueueDrainHelper.Enter(ref wip)) { return; } var a = enumerator; for (;;) { if (!Volatile.Read(ref active)) { int i = index; if (i != 0) { bool hasNext; try { hasNext = enumerator.MoveNext(); } catch (Exception ex) { ExceptionHelper.ThrowIfFatal(ex); Exception exc = error; if (exc != null) { exc = new AggregateException(exc, ex); } actual.OnError(exc); return; } if (!hasNext) { Exception ex = error; if (ex != null) { actual.OnError(ex); } else { actual.OnComplete(); } return; } } long p = produced; if (p != 0L) { produced = 0L; arbiter.Produced(p); } IPublisher <T> next = a.Current; index = i + 1; Volatile.Write(ref active, true); next.Subscribe(this); } if (Interlocked.Decrement(ref wip) == 0) { break; } } }
internal RedisCommand?GetActiveMessage() => Volatile.Read(ref _activeMesssage)?.Command;
private static void AddStat(IDictionary <string, long> stats, string key, ref long value) { stats[I($"DropDaemon.{key}")] = Volatile.Read(ref value); }
public async Task no_data_should_be_dispatched_after_tcp_connection_closed() { for (int i = 0; i < 1000; i++) { bool closed = false; bool dataReceivedAfterClose = false; var listeningSocket = CreateListeningSocket(); var mre = new ManualResetEventSlim(false); var clientTcpConnection = ClientAPI.Transport.Tcp.TcpConnectionSsl.CreateConnectingConnection( new NoopLogger(), Guid.NewGuid(), (IPEndPoint)listeningSocket.LocalEndPoint, "localhost", false, new ClientAPI.Transport.Tcp.TcpClientConnector(), TimeSpan.FromSeconds(5), (conn) => mre.Set(), (conn, error) => { Assert.True(false, $"Connection failed: {error}"); }, (conn, error) => { Volatile.Write(ref closed, true); }); var serverSocket = listeningSocket.Accept(); var serverTcpConnection = TcpConnectionSsl.CreateServerFromSocket(Guid.NewGuid(), (IPEndPoint)serverSocket.RemoteEndPoint, serverSocket, GetCertificate(), false); mre.Wait(TimeSpan.FromSeconds(3)); try { clientTcpConnection.ReceiveAsync((connection, data) => { if (Volatile.Read(ref closed)) { dataReceivedAfterClose = true; } }); using (var b = new Barrier(2)) { Task sendData = Task.Factory.StartNew(() => { b.SignalAndWait(); for (int i = 0; i < 1000; i++) { serverTcpConnection.EnqueueSend(GenerateData()); } }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); Task closeConnection = Task.Factory.StartNew(() => { b.SignalAndWait(); serverTcpConnection.Close("Intentional close"); }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); await Task.WhenAll(sendData, closeConnection); Assert.False(dataReceivedAfterClose); } } finally { clientTcpConnection.Close("Shut down"); serverTcpConnection.Close("Shut down"); listeningSocket.Dispose(); } } }
private void RunTestOnPool(DynamicThreadPool pool, int totalTaskCount, int taskSpinCount, int spawnThreadCount, int spawnSpinTime, bool spawnFromPool) { Random rndGenerator = new Random(); int executedTaskCounter = 0; int completedTaskCount = 0; Action taskAction = null; taskAction = () => { int curTaskSpinCount = taskSpinCount; lock (rndGenerator) curTaskSpinCount = rndGenerator.Next(taskSpinCount); SpinWaitHelper.SpinWait(curTaskSpinCount); if (spawnFromPool) { if (Interlocked.Increment(ref executedTaskCounter) <= totalTaskCount) { pool.Run(taskAction); } } Interlocked.Increment(ref completedTaskCount); }; Barrier bar = new Barrier(spawnThreadCount + 1); Random spawnRndGenerator = new Random(); Thread[] spawnThreads = new Thread[spawnThreadCount]; ThreadStart spawnAction = () => { bar.SignalAndWait(); while (Interlocked.Increment(ref executedTaskCounter) <= totalTaskCount) { pool.Run(taskAction); int curSpawnSpinCount = spawnSpinTime; lock (spawnRndGenerator) curSpawnSpinCount = spawnRndGenerator.Next(spawnSpinTime); SpinWaitHelper.SpinWait(curSpawnSpinCount); } }; for (int i = 0; i < spawnThreads.Length; i++) { spawnThreads[i] = new Thread(spawnAction); } for (int i = 0; i < spawnThreads.Length; i++) { spawnThreads[i].Start(); } bar.SignalAndWait(); TimingAssert.AreEqual(60 * 1000, totalTaskCount, () => Volatile.Read(ref completedTaskCount)); }