/// <summary> /// Deserializes each frame header and copies the body bytes into a single buffer. /// </summary> /// <returns>True if a full operation (streamId) has been processed.</returns> internal bool ReadParse(byte[] buffer, int length) { if (length <= 0) { return(false); } // Check if protocol version has already been determined (first message) ProtocolVersion protocolVersion; var headerLength = Volatile.Read(ref _frameHeaderSize); var serializer = Volatile.Read(ref _serializer); if (headerLength == 0) { // The server replies the first message with the max protocol version supported protocolVersion = FrameHeader.GetProtocolVersion(buffer); serializer = serializer.CloneWithProtocolVersion(protocolVersion); headerLength = protocolVersion.GetHeaderSize(); Volatile.Write(ref _serializer, serializer); Volatile.Write(ref _frameHeaderSize, headerLength); _frameHeaderSize = headerLength; } else { protocolVersion = serializer.ProtocolVersion; } // Use _readStream to buffer between messages, when the body is not contained in a single read call var stream = Interlocked.Exchange(ref _readStream, null); var previousHeader = Interlocked.Exchange(ref _receivingHeader, null); if (previousHeader != null && stream == null) { // This connection has been disposed return(false); } var operationCallbacks = new LinkedList <Action <MemoryStream, long> >(); var offset = 0; while (offset < length) { FrameHeader header; int remainingBodyLength; // check if header has not been read yet if (previousHeader == null) { header = ReadHeader(buffer, ref offset, length, headerLength, protocolVersion); if (header == null) { // There aren't enough bytes to read the header break; } Connection.Logger.Verbose("Received #{0} from {1}", header.StreamId, EndPoint.EndpointFriendlyName); remainingBodyLength = header.BodyLength; } else { header = previousHeader; previousHeader = null; remainingBodyLength = header.BodyLength - (int)stream.Length; } if (remainingBodyLength > length - offset) { // The buffer does not contains the body for the current frame, store it for later StoreReadState(header, stream, buffer, offset, length, operationCallbacks.Count > 0); break; } // Get read stream stream = stream ?? Configuration.BufferPool.GetStream(Connection.StreamReadTag); // Get callback Action <IRequestError, Response, long> callback; if (header.Opcode == EventResponse.OpCode) { callback = EventHandler; } else { var state = RemoveFromPending(header.StreamId); // State can be null when the Connection is being closed concurrently // The original callback is being called with an error, use a Noop here callback = state != null?state.SetCompleted() : OperationState.Noop; } // Write to read stream stream.Write(buffer, offset, remainingBodyLength); // Add callback with deserialize from stream operationCallbacks.AddLast(CreateResponseAction(serializer, header, callback)); offset += remainingBodyLength; } // Invoke callbacks with read stream return(Connection.InvokeReadCallbacks(stream, operationCallbacks, GetTimestamp())); }
internal IKeyRing GetCurrentKeyRingCore(DateTime utcNow, bool forceRefresh = false) { Debug.Assert(utcNow.Kind == DateTimeKind.Utc); // Can we return the cached keyring to the caller? CacheableKeyRing existingCacheableKeyRing = null; if (!forceRefresh) { existingCacheableKeyRing = Volatile.Read(ref _cacheableKeyRing); if (CacheableKeyRing.IsValid(existingCacheableKeyRing, utcNow)) { return(existingCacheableKeyRing.KeyRing); } } // The cached keyring hasn't been created or must be refreshed. We'll allow one thread to // update the keyring, and all other threads will continue to use the existing cached // keyring while the first thread performs the update. There is an exception: if there // is no usable existing cached keyring, all callers must block until the keyring exists. var acquiredLock = false; try { Monitor.TryEnter(_cacheableKeyRingLockObj, (existingCacheableKeyRing != null) ? 0 : Timeout.Infinite, ref acquiredLock); if (acquiredLock) { if (!forceRefresh) { // This thread acquired the critical section and is responsible for updating the // cached keyring. But first, let's make sure that somebody didn't sneak in before // us and update the keyring on our behalf. existingCacheableKeyRing = Volatile.Read(ref _cacheableKeyRing); if (CacheableKeyRing.IsValid(existingCacheableKeyRing, utcNow)) { return(existingCacheableKeyRing.KeyRing); } if (existingCacheableKeyRing != null) { _logger.ExistingCachedKeyRingIsExpired(); } } // It's up to us to refresh the cached keyring. // This call is performed *under lock*. CacheableKeyRing newCacheableKeyRing; try { newCacheableKeyRing = CacheableKeyRingProvider.GetCacheableKeyRing(utcNow); } catch (Exception ex) { if (existingCacheableKeyRing != null) { _logger.ErrorOccurredWhileRefreshingKeyRing(ex); } else { _logger.ErrorOccurredWhileReadingKeyRing(ex); } // Failures that occur while refreshing the keyring are most likely transient, perhaps due to a // temporary network outage. Since we don't want every subsequent call to result in failure, we'll // create a new keyring object whose expiration is now + some short period of time (currently 2 min), // and after this period has elapsed the next caller will try refreshing. If we don't have an // existing keyring (perhaps because this is the first call), then there's nothing to extend, so // each subsequent caller will keep going down this code path until one succeeds. if (existingCacheableKeyRing != null) { Volatile.Write(ref _cacheableKeyRing, existingCacheableKeyRing.WithTemporaryExtendedLifetime(utcNow)); } // The immediate caller should fail so that he can report the error up his chain. This makes it more likely // that an administrator can see the error and react to it as appropriate. The caller can retry the operation // and will probably have success as long as he falls within the temporary extension mentioned above. throw; } Volatile.Write(ref _cacheableKeyRing, newCacheableKeyRing); return(newCacheableKeyRing.KeyRing); } else { // We didn't acquire the critical section. This should only occur if we passed // zero for the Monitor.TryEnter timeout, which implies that we had an existing // (but outdated) keyring that we can use as a fallback. Debug.Assert(existingCacheableKeyRing != null); return(existingCacheableKeyRing.KeyRing); } } finally { if (acquiredLock) { Monitor.Exit(_cacheableKeyRingLockObj); } } }
public void MinBy() { Volatile.Write(ref _listStore, Enumerable.Range(1, N).MinBy(v => - v, _comparer)); }
public void Unlock() { Volatile.Write(ref _level[ThreadId.Get()], 0); }
public bool LocalFindAndPop(object obj) { // Fast path: check the tail. If equal, we can skip the lock. if (m_array[(m_tailIndex - 1) & m_mask] == obj) { object unused = LocalPop(); Debug.Assert(unused == null || unused == obj); return(unused != null); } // Else, do an O(N) search for the work item. The theory of work stealing and our // inlining logic is that most waits will happen on recently queued work. And // since recently queued work will be close to the tail end (which is where we // begin our search), we will likely find it quickly. In the worst case, we // will traverse the whole local queue; this is typically not going to be a // problem (although degenerate cases are clearly an issue) because local work // queues tend to be somewhat shallow in length, and because if we fail to find // the work item, we are about to block anyway (which is very expensive). for (int i = m_tailIndex - 2; i >= m_headIndex; i--) { if (m_array[i & m_mask] == obj) { // If we found the element, block out steals to avoid interference. bool lockTaken = false; try { m_foreignLock.Enter(ref lockTaken); // If we encountered a race condition, bail. if (m_array[i & m_mask] == null) { return(false); } // Otherwise, null out the element. Volatile.Write(ref m_array[i & m_mask], null); // And then check to see if we can fix up the indexes (if we're at // the edge). If we can't, we just leave nulls in the array and they'll // get filtered out eventually (but may lead to superfluous resizing). if (i == m_tailIndex) { m_tailIndex -= 1; } else if (i == m_headIndex) { m_headIndex += 1; } return(true); } finally { if (lockTaken) { m_foreignLock.Exit(useMemoryBarrier: false); } } } } return(false); }
public void ReleaseValueFactory() { Volatile.Write(ref _valueFactory, null); }
private void Close() { Timer.Donate(_wrapped); Volatile.Write(ref _callback, null); GC.SuppressFinalize(this); }
public static void RunParallel(Action action, int times, int maxParallelism, bool useThreadPool = true) { if (action == null) { throw new ArgumentNullException(nameof(action)); } if (times < 0) { throw new ArgumentOutOfRangeException(nameof(times), times, "Number of times to run must be greater than or equal to 0."); } if (maxParallelism < 1) { throw new ArgumentOutOfRangeException(nameof(maxParallelism), maxParallelism, "Max parallelism must be greater than or equal to 1."); } if (times == 0) { return; } maxParallelism = Math.Min(times, maxParallelism); var exception = (Exception)null; var threadsToWaitFor = maxParallelism; using (var noMoreThreadsEvent = new ManualResetEventSlim()) { for (var i = 0; i < maxParallelism; i++) { var work = new Action(() => { try { while (Interlocked.Decrement(ref times) >= 0) { action.Invoke(); } } catch (Exception ex) { Volatile.Write(ref exception, ex); Volatile.Write(ref times, 0); } finally { if (Interlocked.Decrement(ref threadsToWaitFor) == 0) { noMoreThreadsEvent.Set(); } } }); if (useThreadPool) { ThreadPool.QueueUserWorkItem(_ => work.Invoke()); } else { var actionMethod = action.GetMethodInfo(); new Thread(work.Invoke) { Name = $"{nameof(StressUtility)}.{nameof(RunParallel)} ({actionMethod.Name}) dedicated thread {maxParallelism + 1}" }.Start(); } } noMoreThreadsEvent.Wait(); if (Volatile.Read(ref exception) != null) { ExceptionHelper.Rethrow(exception); } } }
public DefaultValueAttribute(Type?type, string?value) { // The null check and try/catch here are because attributes should never throw exceptions. // We would fail to load an otherwise normal class. if (type == null) { return; } try { if (TryConvertFromInvariantString(type, value, out object?convertedValue)) { _value = convertedValue; } else if (type.IsSubclassOf(typeof(Enum)) && value != null) { _value = Enum.Parse(type, value, true); } else if (type == typeof(TimeSpan) && value != null) { _value = TimeSpan.Parse(value); } else { _value = Convert.ChangeType(value, type, CultureInfo.InvariantCulture); } // Looking for ad hoc created TypeDescriptor.ConvertFromInvariantString(Type, string) bool TryConvertFromInvariantString(Type?typeToConvert, string?stringValue, out object?conversionResult) { conversionResult = null; // lazy init reflection objects if (s_convertFromInvariantString == null) { Type? typeDescriptorType = Type.GetType("System.ComponentModel.TypeDescriptor, System.ComponentModel.TypeConverter", throwOnError: false); MethodInfo?mi = typeDescriptorType?.GetMethod("ConvertFromInvariantString", BindingFlags.NonPublic | BindingFlags.Static); Volatile.Write(ref s_convertFromInvariantString, mi == null ? new object() : mi.CreateDelegate(typeof(Func <Type, string, object>))); } if (!(s_convertFromInvariantString is Func <Type?, string?, object> convertFromInvariantString)) { return(false); } try { conversionResult = convertFromInvariantString(typeToConvert, stringValue); } catch { return(false); } return(true); } } catch { } }
public void Cancel() { Volatile.Write(ref cancelled, true); upstream.Cancel(); }
/// <summary> /// An ordered store(store + StoreStore barrier) of an element to a given offset. /// </summary> /// <typeparam name="T">The element type.</typeparam> /// <param name="buffer">The source buffer.</param> /// <param name="offset">Computed via <see cref="ConcurrentCircularArrayQueue{T}.CalcElementOffset"/></param> /// <param name="e"></param> public static void SoElement <T>(T[] buffer, long offset, T e) where T : class => Volatile.Write(ref buffer[offset], e);
public unsafe void CopyFromAscii(string data) { if (IsDefault) { return; } Debug.Assert(_block != null); Debug.Assert(_block.Next == null); Debug.Assert(_block.End == _index); var pool = _block.Pool; var block = _block; var blockIndex = _index; var length = data.Length; var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex; var bytesLeftInBlockMinusSpan = bytesLeftInBlock - 3; fixed(char *pData = data) { var input = pData; var inputEnd = pData + length; var inputEndMinusSpan = inputEnd - 3; while (input < inputEnd) { if (bytesLeftInBlock == 0) { var nextBlock = pool.Lease(); block.End = blockIndex; Volatile.Write(ref block.Next, nextBlock); block = nextBlock; blockIndex = block.Data.Offset; bytesLeftInBlock = block.Data.Count; bytesLeftInBlockMinusSpan = bytesLeftInBlock - 3; } var output = (block.DataFixedPtr + block.End); var copied = 0; for (; input < inputEndMinusSpan && copied < bytesLeftInBlockMinusSpan; copied += 4) { *(output) = (byte)*(input); *(output + 1) = (byte)*(input + 1); *(output + 2) = (byte)*(input + 2); *(output + 3) = (byte)*(input + 3); output += 4; input += 4; } for (; input < inputEnd && copied < bytesLeftInBlock; copied++) { *(output++) = (byte)*(input++); } blockIndex += copied; bytesLeftInBlockMinusSpan -= copied; bytesLeftInBlock -= copied; } } block.End = blockIndex; _block = block; _index = blockIndex; }
public MonocastDisposable(ISignalObserver <T> downstream, MonocastSubject <T> parent) { this.parent = parent; Volatile.Write(ref this.downstream, downstream); }
public RemoveHandlerDisposable(Action removeHandler) { Volatile.Write(ref _removeHandler, removeHandler); }
private void GetChangesFromDb() { if (!trustInterval.Expired) { return; } if (Interlocked.CompareExchange(ref getchanges, 1, 0) == 0) { try { if (!trustInterval.Expired) { return; } var starttime = trustInterval.StartTime; if (starttime != default(DateTime)) { var correction = TimeSpan.FromTicks(DbExpiration.Ticks * 3); starttime = trustInterval.StartTime.Subtract(correction); } trustInterval.Start(DbExpiration); //get and merge changes in cached tenants foreach (var tenantGroup in service.GetUsers(Tenant.DEFAULT_TENANT, starttime).Values.GroupBy(u => u.Tenant)) { var users = cache.Get <IDictionary <Guid, UserInfo> >(GetUserCacheKey(tenantGroup.Key)); if (users != null) { lock (users) { foreach (var u in tenantGroup) { users[u.ID] = u; } } } } foreach (var tenantGroup in service.GetGroups(Tenant.DEFAULT_TENANT, starttime).Values.GroupBy(g => g.Tenant)) { var groups = cache.Get <IDictionary <Guid, Group> >(GetGroupCacheKey(tenantGroup.Key)); if (groups != null) { lock (groups) { foreach (var g in tenantGroup) { groups[g.Id] = g; } } } } foreach (var tenantGroup in service.GetUserGroupRefs(Tenant.DEFAULT_TENANT, starttime).Values.GroupBy(r => r.Tenant)) { var refs = cache.Get <UserGroupRefStore>(GetRefCacheKey(tenantGroup.Key)); if (refs != null) { lock (refs) { foreach (var r in tenantGroup) { refs[r.CreateKey()] = r; } } } } } finally { Volatile.Write(ref getchanges, 0); } } }
public void MakeReadOnly() { EnsureNotDisposed(); Volatile.Write(ref _readOnly, true); }
/// <summary>Tries to dequeue an element from the queue.</summary> public bool TryDequeue(out T item) { Slot[] slots = _slots; // Loop in case of contention... var spinner = new SpinWait(); while (true) { // Get the head at which to try to dequeue. int currentHead = Volatile.Read(ref _headAndTail.Head); int slotsIndex = currentHead & _slotsMask; // Read the sequence number for the head position. int sequenceNumber = Volatile.Read(ref slots[slotsIndex].SequenceNumber); // We can dequeue from this slot if it's been filled by an enqueuer, which // would have left the sequence number at pos+1. int diff = sequenceNumber - (currentHead + 1); if (diff == 0) { // We may be racing with other dequeuers. Try to reserve the slot by incrementing // the head. Once we've done that, no one else will be able to read from this slot, // and no enqueuer will be able to read from this slot until we've written the new // sequence number. WARNING: The next few lines are not reliable on a runtime that // supports thread aborts. If a thread abort were to sneak in after the CompareExchange // but before the Volatile.Write, enqueuers trying to enqueue into this slot would // spin indefinitely. If this implementation is ever used on such a platform, this // if block should be wrapped in a finally / prepared region. if (Interlocked.CompareExchange(ref _headAndTail.Head, currentHead + 1, currentHead) == currentHead) { // Successfully reserved the slot. Note that after the above CompareExchange, other threads // trying to dequeue from this slot will end up spinning until we do the subsequent Write. item = slots[slotsIndex].Item; if (!Volatile.Read(ref _preservedForObservation)) { // If we're preserving, though, we don't zero out the slot, as we need it for // enumerations, peeking, ToArray, etc. And we don't update the sequence number, // so that an enqueuer will see it as full and be forced to move to a new segment. slots[slotsIndex].Item = default(T); Volatile.Write(ref slots[slotsIndex].SequenceNumber, currentHead + slots.Length); } return(true); } } else if (diff < 0) { // The sequence number was less than what we needed, which means this slot doesn't // yet contain a value we can dequeue, i.e. the segment is empty. Technically it's // possible that multiple enqueuers could have written concurrently, with those // getting later slots actually finishing first, so there could be elements after // this one that are available, but we need to dequeue in order. So before declaring // failure and that the segment is empty, we check the tail to see if we're actually // empty or if we're just waiting for items in flight or after this one to become available. bool frozen = _frozenForEnqueues; int currentTail = Volatile.Read(ref _headAndTail.Tail); if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0))) { item = default(T); return(false); } // It's possible it could have become frozen after we checked _frozenForEnqueues // and before reading the tail. That's ok: in that rare race condition, we just // loop around again. } // Lost a race. Spin a bit, then try again. spinner.SpinOnce(sleep1Threshold: -1); } }
void InnerComplete() { Volatile.Write(ref active, false); Drain(); }
private bool WaitUpgrade() { var owner = Volatile.Read(ref _ownerThread); if (owner == null || owner == Thread.CurrentThread) { var spinWait = new SpinWait(); while (true) { var status = (Status)Volatile.Read(ref _status); switch (status) { case Status.WriteRequested: // Write mode already requested // We are going to steal it // Reserve the lock - so no other writer can take it owner = Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null); if (owner == null || owner == Thread.CurrentThread) { // Set the edge Volatile.Write(ref _edge, _currentReadingCount.Value); } else { // It was reserved by another thread - abort mission return(false); } if (Volatile.Read(ref _readCount) > Volatile.Read(ref _edge)) { // We still need every other reader to finish _freeToWrite.Wait(); // Status must have changed } else { // None to wait // Change to write mode Interlocked.CompareExchange(ref _status, (int)Status.WriteMode, (int)Status.WriteRequested); } break; case Status.WriteMode: // There is a writer // Abort mission _freeToRead.Reset(); Interlocked.Increment(ref _writeCount); return(true); case Status.Free: // Free to proceed UPGRADE // Change to write mode status = (Status)Interlocked.CompareExchange(ref _status, (int)Status.WriteMode, (int)Status.Free); if (status == Status.Free) { // Did change to write mode, no more readers should enter _freeToRead.Reset(); // Take the lock if (Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null) == null) { // Success Interlocked.Increment(ref _writeCount); return(true); } } // Write mode was taken by another thread break; case Status.ReadMode: // There are readers currently - of course, current thread is a reader // Requesting write mode status = (Status)Interlocked.CompareExchange(ref _status, (int)Status.WriteRequested, (int)Status.ReadMode); if (status == Status.ReadMode) { // Write has been requested, no more readers should enter _freeToRead.Reset(); } break; default: // Should not happen break; } spinWait.SpinOnce(); } } return(false); }
void Drain() { if (Interlocked.Increment(ref wip) != 1) { return; } int missed = 1; var a = actual; var q = queue; int c = consumed; for (;;) { if (ArbiterIsCancelled()) { queue.Clear(); return; } if (!Volatile.Read(ref active)) { bool d = Volatile.Read(ref done); bool empty = !q.Poll(out T v); if (d && empty) { Exception ex = ExceptionHelper.Terminate(ref error); if (ex != null) { a.OnError(ex); } else { a.OnComplete(); } return; } if (!empty) { if (fusionMode != FusionSupport.SYNC && ++c == limit) { c = 0; upstream.Request(limit); } IPublisher<R> p; try { p = mapper(v); if (p == null) { throw new NullReferenceException("The mapper returned a null IPublisher"); } } catch (Exception ex) { upstream.Cancel(); q.Clear(); ExceptionHelper.AddException(ref error, ex); a.OnError(ExceptionHelper.Terminate(ref error)); return; } long e = inner.produced; if (e != 0L) { inner.produced = 0L; ArbiterProduced(e); } Volatile.Write(ref active, true); p.Subscribe(inner); } } int w = Volatile.Read(ref wip); if (w == missed) { consumed = c; missed = Interlocked.Add(ref wip, -missed); if (missed == 0) { break; } } else { missed = w; } } }
public void Stop() { Volatile.Write(ref _stop, true); }
/// <inheritdoc /> public override string ToString() { if (str != null) { return(str); } var builder = new StringBuilder(); var localTarget = target; var isCollection = false; var anyMoreItems = false; if (target is IEnumerable <object> enu) { isCollection = true; using (var e = enu.GetEnumerator()) { if (e.MoveNext()) { localTarget = e.Current; anyMoreItems = e.MoveNext(); } else { localTarget = null; builder.Append("{[]}"); } } } if (localTarget != null) { if (isCollection) { builder.Append('['); } var type = localTarget.GetType().GetTypeInfo(); if (!type.IsPrimitive && !type.Namespace.StartsWith("System.")) { builder.Append(type.Name); } builder.Append('{'); builder.Append(localTarget); builder.Append('}'); if (anyMoreItems) { builder.Append(", …"); } if (isCollection) { builder.Append(']'); } } builder.Append("::"); builder.Append(action); builder.Append('('); var isFirst = true; foreach (var p in parameters) { if (isFirst) { isFirst = false; } else { builder.Append(", "); } builder.Append(p); } builder.Append(')'); var localStr = builder.ToString(); Volatile.Write(ref str, localStr); return(localStr); }
public void LocalPush(ISpreadsThreadPoolWorkItem obj) { int tail = m_tailIndex; // We're going to increment the tail; if we'll overflow, then we need to reset our counts if (tail == int.MaxValue) { bool lockTaken = false; try { m_foreignLock.Enter(ref lockTaken); if (m_tailIndex == int.MaxValue) { // // Rather than resetting to zero, we'll just mask off the bits we don't care about. // This way we don't need to rearrange the items already in the queue; they'll be found // correctly exactly where they are. One subtlety here is that we need to make sure that // if head is currently < tail, it remains that way. This happens to just fall out from // the bit-masking, because we only do this if tail == int.MaxValue, meaning that all // bits are set, so all of the bits we're keeping will also be set. Thus it's impossible // for the head to end up > than the tail, since you can't set any more bits than all of // them. // m_headIndex = m_headIndex & m_mask; m_tailIndex = tail = m_tailIndex & m_mask; Debug.Assert(m_headIndex <= m_tailIndex); } } finally { if (lockTaken) { m_foreignLock.Exit(useMemoryBarrier: true); } } } // When there are at least 2 elements' worth of space, we can take the fast path. if (tail < m_headIndex + m_mask) { Volatile.Write(ref m_array[tail & m_mask], obj); m_tailIndex = tail + 1; } else { // We need to contend with foreign pops, so we lock. bool lockTaken = false; try { m_foreignLock.Enter(ref lockTaken); int head = m_headIndex; int count = m_tailIndex - m_headIndex; // If there is still space (one left), just add the element. if (count >= m_mask) { // We're full; expand the queue by doubling its size. var newArray = new ISpreadsThreadPoolWorkItem[m_array.Length << 1]; for (int i = 0; i < m_array.Length; i++) { newArray[i] = m_array[(i + head) & m_mask]; } // Reset the field values, incl. the mask. m_array = newArray; m_headIndex = 0; m_tailIndex = tail = count; m_mask = (m_mask << 1) | 1; } Volatile.Write(ref m_array[tail & m_mask], obj); m_tailIndex = tail + 1; } finally { if (lockTaken) { m_foreignLock.Exit(useMemoryBarrier: false); } } } }
public void Leave() { // 标记资源"未使用" Volatile.Write(ref resourceInUse, 0); }
public void Dispose() { // Exit File Event Consumer Thread Volatile.Write(ref keepConsuming, false); fileEventConsumer.Join(); }
public void OnCompleted() { Volatile.Write(ref _done, true); Drain(); }
public void Write(ref int transactionDepth, int depth) { Volatile.Write(ref transactionDepth, depth); }
private static void LoadMachineStores() { Debug.Assert( Monitor.IsEntered(s_machineLoadLock), "LoadMachineStores assumes a lock(s_machineLoadLock)"); var rootStore = new List <X509Certificate2>(); var intermedStore = new List <X509Certificate2>(); DirectoryInfo rootStorePath = null; IEnumerable <FileInfo> trustedCertFiles; try { rootStorePath = new DirectoryInfo(Interop.Crypto.GetX509RootStorePath()); } catch (ArgumentException) { // If SSL_CERT_DIR is set to the empty string, or anything else which gives // "The path is not of a legal form", then the GetX509RootStorePath value is ignored. } if (rootStorePath != null && rootStorePath.Exists) { trustedCertFiles = rootStorePath.EnumerateFiles(); } else { trustedCertFiles = Array.Empty <FileInfo>(); } FileInfo rootStoreFile = null; try { rootStoreFile = new FileInfo(Interop.Crypto.GetX509RootStoreFile()); } catch (ArgumentException) { // If SSL_CERT_FILE is set to the empty string, or anything else which gives // "The path is not of a legal form", then the GetX509RootStoreFile value is ignored. } if (rootStoreFile != null && rootStoreFile.Exists) { trustedCertFiles = trustedCertFiles.Prepend(rootStoreFile); } HashSet <X509Certificate2> uniqueRootCerts = new HashSet <X509Certificate2>(); HashSet <X509Certificate2> uniqueIntermediateCerts = new HashSet <X509Certificate2>(); foreach (FileInfo file in trustedCertFiles) { using (SafeBioHandle fileBio = Interop.Crypto.BioNewFile(file.FullName, "rb")) { // The handle may be invalid, for example when we don't have read permission for the file. if (fileBio.IsInvalid) { Interop.Crypto.ErrClearError(); continue; } ICertificatePal pal; // Some distros ship with two variants of the same certificate. // One is the regular format ('BEGIN CERTIFICATE') and the other // contains additional AUX-data ('BEGIN TRUSTED CERTIFICATE'). // The additional data contains the appropriate usage (e.g. emailProtection, serverAuth, ...). // Because corefx doesn't validate for a specific usage, derived certificates are rejected. // For now, we skip the certificates with AUX data and use the regular certificates. while (OpenSslX509CertificateReader.TryReadX509PemNoAux(fileBio, out pal) || OpenSslX509CertificateReader.TryReadX509Der(fileBio, out pal)) { X509Certificate2 cert = new X509Certificate2(pal); // The HashSets are just used for uniqueness filters, they do not survive this method. if (StringComparer.Ordinal.Equals(cert.Subject, cert.Issuer)) { if (uniqueRootCerts.Add(cert)) { rootStore.Add(cert); continue; } } else { if (uniqueIntermediateCerts.Add(cert)) { intermedStore.Add(cert); continue; } } // There's a good chance we'll encounter duplicates on systems that have both one-cert-per-file // and one-big-file trusted certificate stores. Anything that wasn't unique will end up here. cert.Dispose(); } } } var rootStorePal = new CollectionBackedStoreProvider(rootStore); s_machineIntermediateStore = new CollectionBackedStoreProvider(intermedStore); // s_machineRootStore's nullarity is the loaded-state sentinel, so write it with Volatile. Debug.Assert(Monitor.IsEntered(s_machineLoadLock), "LoadMachineStores assumes a lock(s_machineLoadLock)"); Volatile.Write(ref s_machineRootStore, rootStorePal); }
public void Max() { Volatile.Write(ref _store, Enumerable.Range(1, N).Max(_comparer)); }
/// <summary> /// Freezes the report disallowing further modification /// </summary> internal void Freeze() { Volatile.Write(ref m_isFrozen, true); }