Пример #1
0
        public override void Free(LockFreeNode <T> node)
        {
            node.Item = default(T);             // Allow early GC

            // Try to make the new node be the head of the stack
            do
            {
                // Make the new node refer to the old head
                node.Next = m_head.Next;

                // If previous head's next == what we thought was next, change head's Next to the new node
                // else, try again if another thread changed the head
            } while (!InterlockedEx.IfThen(ref m_head.Next, node.Next, node));
        }
Пример #2
0
        public Boolean TryDequeue(out T item)
        {
            item = default(T);

            // Loop until we manage to advance the head, removing
            // a node (if there are no nodes to dequeue, we'll exit the method instead)
            for (Boolean dequeuedNode = false; !dequeuedNode;)
            {
                // make local copies of the head, the tail, and the head's Next reference
                LockFreeNode <T> tempHead     = m_head;
                LockFreeNode <T> tempTail     = m_tail;
                LockFreeNode <T> tempHeadNext = tempHead.Next;

                // If another thread changed the head, start over
                Thread.MemoryBarrier();                 // Make sure the value read from m_head is fresh

                if (tempHead != m_head)
                {
                    continue;
                }

                // If the head equals the tail
                if (tempHead == tempTail)
                {
                    // If the head node refers to null, then the queue is empty
                    if (tempHeadNext == null)
                    {
                        return(false);
                    }

                    // The head refers to the tail whose Next is not null. This means
                    // we have a lagging tail; update it
                    InterlockedEx.IfThen(ref m_tail, tempTail, tempHeadNext);
                    continue;
                }

                // The head and tail nodes are different; dequeue the head node and advance the head
                item         = tempHeadNext.Item;
                dequeuedNode = InterlockedEx.IfThen(ref m_head, tempHead, tempHeadNext);

                if (dequeuedNode)
                {
                    m_nodeManager.Free(tempHead);
                }
            }
            //Interlocked.Decrement(ref m_count);
            return(true);
        }
        private Int32 NumReadersToWake()
        {
            Int32 ls = m_LockState, numReadersWaiting;

            // If lock is Free && RW>0, try to subtract all readers
            while ((State(ls) == OneManyLockStates.Free) && ((numReadersWaiting = NumReadersWaiting(ls)) > 0))
            {
                Int32 desired = ls;
                DecReadersWaiting(ref desired, numReadersWaiting);
                if (InterlockedEx.IfThen(ref m_LockState, ls, desired, out ls))
                {
                    // We sucessfully subtracted all waiting readers, wake them up
                    return(numReadersWaiting);
                }
            }
            return(0);
        }
        private Int32 NumWritersToWake()
        {
            Int32 ls = m_LockState;

            // If lock is RFW && WW>0, try to subtract 1 writer
            while ((State(ls) == OneManyLockStates.ReservedForWriter) && (NumWritersWaiting(ls) > 0))
            {
                Int32 desired = ls;
                DecWritersWaiting(ref desired);
                if (InterlockedEx.IfThen(ref m_LockState, ls, desired, out ls))
                {
                    // We sucessfully subtracted 1 waiting writer, wake it up
                    return(1);
                }
            }
            return(0);
        }
Пример #5
0
        // If two threads call Enqueue simultaneously:
        // Both threads create and initialize a new node
        // The tail's Next will refer to one of these 2 new nodes
        // The new new tail's Next will refer to the other of the 2 new nodes
        // m_tail will refer to the 1st new node appended (not the real tail)
        // To fix this: Enqueue initializes by advancing m_tail to the node whose Next is null
        public void Enqueue(T item)
        {
            // Get (or allocate) a node and initialize it
            LockFreeNode <T> newNode = m_nodeManager.Allocate(item);

            LockFreeNode <T> tempTail = null;

            for (Boolean appendedNewNode = false; !appendedNewNode;)
            {
                // Get the current tail and what IT refers to
                tempTail = m_tail;
                LockFreeNode <T> tempTailNext = tempTail.Next;

                // If another thread changed the tail, start over
                Thread.MemoryBarrier();                 // Make sure the value read from m_tail is fresh

                if (tempTail != m_tail)
                {
                    continue;
                }

                // If the tail isn't truely the tail, fix the tail, start over
                if (tempTailNext != null)
                {
                    // This can happen if multiple threads append nodes at the same time
                    // A new node thinks it's the tail (Next is null) as another thread's new node
                    // updates the previous node's Nextthinks it's the tail's Next field may not
                    InterlockedEx.IfThen(ref m_tail, tempTail, tempTailNext);
                    continue;
                }

                // The tail is truely the tail, try to append the new node
                appendedNewNode = InterlockedEx.IfThen(ref tempTail.Next, null, newNode);
            }

            // When new node is sucessfully appended, make the tail refer to it
            // This can fail if another thread scoots in. If this happens, our node is
            // appended to the linked-list but m_tail refers to another node that is not
            // the tail. The next Enqueue/Dequeue call will fix m_tail
            InterlockedEx.IfThen(ref m_tail, tempTail, newNode);

            //Interlocked.Increment(ref m_count);
        }
Пример #6
0
        public override LockFreeNode <T> Allocate(T item)
        {
            LockFreeNode <T> node;

            do
            {
                // Get head
                node = m_head.Next;

                // If no head, stack is empty, return new node
                if (node == null)
                {
                    return(new LockFreeNode <T>(item));
                }

                // If previous head == what we think is head, change head to next node
                // else try again
            } while (!InterlockedEx.IfThen(ref m_head.Next, node, node.Next));
            node.Item = item;
            return(node);
        }
Пример #7
0
 private void AddThreadIdWithRecurseCountOf1(Int32 callingThreadId)
 {
     Contract.Assume(m_ReaderThreadIdsAndRecurseCounts != null);
     // The JITter produces more efficient code if we load the array reference into a temporary
     ThreadIdAndRecurseCount[] readerThreadIdsAndRecurseCounts = m_ReaderThreadIdsAndRecurseCounts;
     for (Int32 index = 0; index < readerThreadIdsAndRecurseCounts.Length; index++)
     {
         if (readerThreadIdsAndRecurseCounts[index].m_Id == 0)
         {
             if (InterlockedEx.IfThen(ref readerThreadIdsAndRecurseCounts[index].m_Id, 0, callingThreadId))
             {
                 readerThreadIdsAndRecurseCounts[index].m_Count = 1;
                 return;
             }
             else
             {
                 // We found a slot but then it was taken away from us
                 index = -1; // Start the search over again from the beginning
                 continue;
             }
         }
     }
     throw new InvalidOperationException("More current reader threads than allowed!");
 }
Пример #8
0
        public GoldCalculator(IUserSubAccountBll subAccountBll,
                              IUserBll userBll, IHangUpTimeBll hangUpTimeBll)
        {
            _subAccountBll = subAccountBll;
            _userBll       = userBll;
            _hangUpTimeBll = hangUpTimeBll;
            _creator       = userId =>
            {
                return(_subAccountBll.Count(userId));
            };

            _timer = new Timer(obj =>
            {
                if (InterlockedEx.IfThen(ref _isExecuted, 1, 1))
                {
                    return;
                }

                Interlocked.Increment(ref _isExecuted);

                try
                {
                    foreach (var sessionId in Global.GetConnectedClientUserId())
                    {
                        if (sessionId.LastCalcTime.Value.AddMinutes(10) <= DateTime.Now)
                        {
                            _hangUpTimeBll.Add(new HangUpTime
                            {
                                UserId  = sessionId.Id,
                                Minutes = 10
                            });

                            var count = CacheManager.GetSubAccountCount(sessionId.Id, _creator);
                            int gold  = 0;
                            if (count == 1)
                            {
                                gold = 5;
                            }
                            else if (count == 2)
                            {
                                gold = 8;
                            }
                            else if (count >= 3)
                            {
                                gold = 13;
                            }

                            if (gold != 0)
                            {
                                _userBll.UpdateGold(sessionId.Id, gold);
                            }

                            sessionId.LastCalcTime = sessionId.LastCalcTime.Value.AddMinutes(10);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Global.Resolve <ILoggerFactory>()
                    .GetCurrentClassLogger()
                    .ErrorException("GoldCalculator Timer Callback.", ex);
                }
                finally
                {
                    Interlocked.Decrement(ref _isExecuted);
                }
            }, null, Timeout.Infinite, CalculatePeriod);
        }
Пример #9
0
 protected static Boolean IfThen(ref Int32 value, Int32 @if, Int32 then, out Int32 previousValue)
 {
     return(InterlockedEx.IfThen(ref value, @if, then, out previousValue));
 }
Пример #10
0
 protected static Boolean IfThen(ref Int32 value, Int32 @if, Int32 then)
 {
     return(InterlockedEx.IfThen(ref value, @if, then));
 }