private void Push(T context) { int currentProcessorId = CurrentProcessorIdHelper.GetCurrentProcessorId() % _perCoreContexts.Length; var core = _perCoreContexts[currentProcessorId]; for (int i = 0; i < core.Length; i++) { if (core[i] != null) { continue; } if (Interlocked.CompareExchange(ref core[i], context, null) == null) { return; } } if (LowMemoryFlag.IsRaised()) { context.Dispose(); return; } // couldn't find a place for it, let's add it to the global list _globalQueue.Enqueue(context); }
public IDisposable AllocateOperationContext(out T context) { _cts.Token.ThrowIfCancellationRequested(); var coreItems = _perCoreContexts[CurrentProcessorIdHelper.GetCurrentProcessorId() % _perCoreContexts.Length]; for (int i = 0; i < coreItems.Length; i++) { context = coreItems[i]; if (context == null) { continue; } if (Interlocked.CompareExchange(ref coreItems[i], null, context) != context) { continue; } if (context.InUse.Raise() == false) { // This what ensures that we work correctly with races from other threads // if there is a context switch at the wrong time continue; } context.Renew(); return(new ReturnRequestContext { Parent = this, Context = context }); } while (_globalQueue.TryDequeue(out context)) { if (context.InUse.Raise() == false) { continue; } context.Renew(); return(new ReturnRequestContext { Parent = this, Context = context }); } // no choice, got to create it context = CreateContext(); context.PoolGeneration = _generation; return(new ReturnRequestContext { Parent = this, Context = context }); }
public bool TryPush(T cur) { var core = _perCoreArrays[CurrentProcessorIdHelper.GetCurrentProcessorId() % _perCoreArrays.Length]; for (int i = 0; i < core.Length; i++) { if (core[i] != null) continue; if (Interlocked.CompareExchange(ref core[i], cur, null) == null) return true; } return false; }
public bool TryPull(out T output) { var coreItems = _perCoreArrays[CurrentProcessorIdHelper.GetCurrentProcessorId() % _perCoreArrays.Length]; for (int i = 0; i < coreItems.Length; i++) { var cur = coreItems[i]; if (cur == null) continue; if (Interlocked.CompareExchange(ref coreItems[i], null, cur) != cur) continue; output = cur; return true; } output = default; return false; }
public void Log(ref LogEntry entry, TaskCompletionSource <object> tcs = null) { var state = _localState.Value; if (state.Generation != _generation) { state = _localState.Value = GenerateThreadWriterState(); } int currentProcessNumber = CurrentProcessorIdHelper.GetCurrentProcessorId() % _freePooledMessageEntries.Length; var pool = _freePooledMessageEntries[currentProcessNumber]; if (pool.TryDequeue(out var item)) { item.Data.SetLength(0); item.WebSocketsList.Clear(); item.Task = tcs; state.ForwardingStream.Destination = item.Data; } else { item = new LogMessageEntry { Task = tcs }; state.ForwardingStream.Destination = new MemoryStream(); } foreach (var kvp in _listeners) { if (kvp.Value.Filter.Forward(ref entry)) { item.WebSocketsList.Add(kvp.Key); } } WriteEntryToWriter(state.Writer, ref entry); item.Data = state.ForwardingStream.Destination; Debug.Assert(item.Data != null); item.Type = entry.Type; _activePoolMessageEntries[currentProcessNumber].Enqueue(item, 128); _hasEntries.Set(); }