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); }
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); }
/// <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); }