コード例 #1
0
ファイル: Connection.cs プロジェクト: weexp/csharp-driver
        /// <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()));
        }
コード例 #2
0
        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);
                }
            }
        }
コード例 #3
0
 public void MinBy()
 {
     Volatile.Write(ref _listStore, Enumerable.Range(1, N).MinBy(v => - v, _comparer));
 }
コード例 #4
0
 public void Unlock()
 {
     Volatile.Write(ref _level[ThreadId.Get()], 0);
 }
コード例 #5
0
ファイル: ThreadPoolWorkQueue.cs プロジェクト: pangfd/Spreads
            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);
            }
コード例 #6
0
ファイル: LazyNeedle.cs プロジェクト: NN---/Theraot
 public void ReleaseValueFactory()
 {
     Volatile.Write(ref _valueFactory, null);
 }
コード例 #7
0
 private void Close()
 {
     Timer.Donate(_wrapped);
     Volatile.Write(ref _callback, null);
     GC.SuppressFinalize(this);
 }
コード例 #8
0
ファイル: StressUtility.cs プロジェクト: pakrym/nunit
        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);
                }
            }
        }
コード例 #9
0
        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
            {
            }
        }
コード例 #10
0
 public void Cancel()
 {
     Volatile.Write(ref cancelled, true);
     upstream.Cancel();
 }
コード例 #11
0
ファイル: RefArrayAccessUtil.cs プロジェクト: wxlonstar/Fenix
 /// <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);
コード例 #12
0
        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;
        }
コード例 #13
0
 public MonocastDisposable(ISignalObserver <T> downstream, MonocastSubject <T> parent)
 {
     this.parent = parent;
     Volatile.Write(ref this.downstream, downstream);
 }
コード例 #14
0
 public RemoveHandlerDisposable(Action removeHandler)
 {
     Volatile.Write(ref _removeHandler, removeHandler);
 }
コード例 #15
0
        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);
                }
            }
        }
コード例 #16
0
ファイル: SecureString.cs プロジェクト: pedrobsaila/runtime
 public void MakeReadOnly()
 {
     EnsureNotDisposed();
     Volatile.Write(ref _readOnly, true);
 }
コード例 #17
0
        /// <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);
            }
        }
コード例 #18
0
 void InnerComplete()
 {
     Volatile.Write(ref active, false);
     Drain();
 }
コード例 #19
0
        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);
        }
コード例 #20
0
            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;
                    }
                }
            }
コード例 #21
0
 public void Stop()
 {
     Volatile.Write(ref _stop, true);
 }
コード例 #22
0
            /// <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);
            }
コード例 #23
0
ファイル: ThreadPoolWorkQueue.cs プロジェクト: pangfd/Spreads
            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);
                        }
                    }
                }
            }
コード例 #24
0
ファイル: SimpleSpinLock.cs プロジェクト: luwanchao915/Thread
 public void Leave()
 {
     // 标记资源"未使用"
     Volatile.Write(ref resourceInUse, 0);
 }
コード例 #25
0
ファイル: FileMimic.cs プロジェクト: puglisij/Mimic
 public void Dispose()
 {
     // Exit File Event Consumer Thread
     Volatile.Write(ref keepConsuming, false);
     fileEventConsumer.Join();
 }
コード例 #26
0
 public void OnCompleted()
 {
     Volatile.Write(ref _done, true);
     Drain();
 }
コード例 #27
0
 public void Write(ref int transactionDepth, int depth)
 {
     Volatile.Write(ref transactionDepth, depth);
 }
コード例 #28
0
ファイル: StorePal.cs プロジェクト: shandan1/CollectionRef
        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);
        }
コード例 #29
0
 public void Max()
 {
     Volatile.Write(ref _store, Enumerable.Range(1, N).Max(_comparer));
 }
コード例 #30
0
 /// <summary>
 /// Freezes the report disallowing further modification
 /// </summary>
 internal void Freeze()
 {
     Volatile.Write(ref m_isFrozen, true);
 }