예제 #1
0
        private bool TryTakeOrPeek(out T result, bool take)
        {
            ThreadLocalList list = GetThreadList(false);

            if (list == null || list.Count == 0)
            {
                return(Steal(out result, take));
            }

            bool lockTaken = false;

            try {
                if (take)
                {
                    Interlocked.Exchange(ref list._currentOp, (int)ListOperation.Take);

                    if (list.Count <= 2 || _needSync)
                    {
                        list._currentOp = (int)ListOperation.None;
                        Monitor.Enter(list, ref lockTaken);


                        if (list.Count == 0)
                        {
                            if (lockTaken)
                            {
                                try { }
                                finally {
                                    lockTaken = false;
                                    Monitor.Exit(list);
                                }
                            }
                            return(Steal(out result, true));
                        }
                    }
                    list.Remove(out result);
                }
                else
                {
                    if (!list.Peek(out result))
                    {
                        return(Steal(out result, false));
                    }
                }
            }
            finally {
                list._currentOp = (int)ListOperation.None;
                if (lockTaken)
                {
                    Monitor.Exit(list);
                }
            }
            return(true);
        }
예제 #2
0
        private bool TryTakeOrPeek(out T result, bool take)
        {
            ThreadLocalList <T> threadList = this.GetThreadList(false);

            if ((threadList == null) || (threadList.Count == 0))
            {
                return(this.Steal(out result, take));
            }
            bool lockTaken = false;

            try
            {
                if (take)
                {
                    Interlocked.Exchange(ref threadList.m_currentOp, 2);
                    if ((threadList.Count <= 2) || this.m_needSync)
                    {
                        threadList.m_currentOp = 0;
                        Monitor.Enter(threadList, ref lockTaken);
                        if (threadList.Count == 0)
                        {
                            if (lockTaken)
                            {
                                try
                                {
                                }
                                finally
                                {
                                    lockTaken = false;
                                    Monitor.Exit(threadList);
                                }
                            }
                            return(this.Steal(out result, true));
                        }
                    }
                    threadList.Remove(out result);
                }
                else if (!threadList.Peek(out result))
                {
                    return(this.Steal(out result, false));
                }
            }
            finally
            {
                threadList.m_currentOp = 0;
                if (lockTaken)
                {
                    Monitor.Exit(threadList);
                }
            }
            return(true);
        }
예제 #3
0
        /// <summary>
        /// Local helper function to Take or Peek an item from the bag
        /// </summary>
        /// <param name="result">To receive the item retrieved from the bag</param>
        /// <param name="take">True means Take operation, false means Peek operation</param>
        /// <returns>True if succeeded, false otherwise</returns>
        private bool TryTakeOrPeek(out T result, bool take)
        {
            // Get the local list for that thread, return null if the thread doesn't exit
            //(this thread never add before)
            ThreadLocalList list = GetThreadList(false);

            if (list == null || list.Count == 0)
            {
                return(Steal(out result, take));
            }

            bool lockTaken = false;

            try
            {
                if (take) // Take operation
                {
#pragma warning disable 0420
                    Interlocked.Exchange(ref list._currentOp, (int)ListOperation.Take);
#pragma warning restore 0420
                    //Synchronization cases:
                    // if the list count is less than or equal two to avoid conflict with any stealing thread
                    // if _needSync is set, this means there is a thread that needs to freeze the bag
                    if (list.Count <= 2 || _needSync)
                    {
                        // reset it back to zero to avoid deadlock with stealing thread
                        list._currentOp = (int)ListOperation.None;
                        Monitor.Enter(list, ref lockTaken);

                        // Double check the count and steal if it became empty
                        if (list.Count == 0)
                        {
                            // Release the lock before stealing
                            if (lockTaken)
                            {
                                try { }
                                finally
                                {
                                    lockTaken = false; // reset lockTaken to avoid calling Monitor.Exit again in the finally block
                                    Monitor.Exit(list);
                                }
                            }
                            return(Steal(out result, true));
                        }
                    }
                    list.Remove(out result);
                }
                else
                {
                    if (!list.Peek(out result))
                    {
                        return(Steal(out result, false));
                    }
                }
            }
            finally
            {
                list._currentOp = (int)ListOperation.None;
                if (lockTaken)
                {
                    Monitor.Exit(list);
                }
            }
            return(true);
        }