/// <summary> /// Pop an item from the head of the queue. /// </summary> /// <remarks> /// NOTE: TrySteal() can be invoked from any thread. /// </remarks> /// <param name="item">Head item of the queue when operation is successful.</param> /// <returns><see langword="True"/> if operation was successful.</returns> public bool TrySteal(out T item) { // read top TopData curTop = _top; // read bottom BottomData curBottom = _bottom; if (IsEmpty(curBottom, curTop, _capacity)) { item = default(T); if (ReferenceEquals(curTop, _top)) { return(false); } else { // NOTE (steveb): this is contentious access case; we currently return 'false' but may want to differentiate in the future return(false); } } // if deque isn't empty, calcuate next top pointer TopData newTop; if (curTop.Index != 0) { // stay at current node newTop = new TopData(curTop.Tag, curTop.Node, curTop.Index - 1); } else { // move to next node and update tag newTop = new TopData(curTop.Tag + 1, curTop.Node.Prev, _capacity - 1); } // read value T retVal = curTop.Node.Data[curTop.Index]; // try updating _top using CAS if (SysUtil.CAS(ref _top, curTop, newTop)) { // clear out the entry we read, so the GC can reclaim it SysUtil.CAS(ref curTop.Node.Data[curTop.Index], retVal, default(T)); // free old node curTop.Node.Next = null; item = retVal; return(true); } else { item = default(T); // NOTE (steveb): this is contentious access case; we currently return 'false' but may want to differentiate in the future return(false); } }
/// <summary> /// Create a new instance. /// </summary> /// <param name="capacity">Maximum number of items in the queue.</param> public WorkStealingDeque(int capacity) { _capacity = capacity; DequeNode nodeB = new DequeNode(_capacity, null); DequeNode nodeA = new DequeNode(_capacity, nodeB); _bottom = new BottomData(nodeA, _capacity - 1); _top = new TopData(0, nodeA, _capacity - 1); }
//--- Class Methods --- private static bool IsEmpty(BottomData bottom, TopData top, int capacity) { if (ReferenceEquals(bottom.Node, top.Node) && ((bottom.Index == top.Index) || (bottom.Index == (top.Index + 1)))) { return(true); } else if (ReferenceEquals(bottom.Node, top.Node.Next) && (bottom.Index == 0) && (top.Index == (capacity - 1))) { return(true); } return(false); }
static public void ShowPanel(List <KeyValuePair <string, string> > showText, string imageLocation, Control panel2) { BottomData bottomData; ///创建BottomData if (!_dicBottomData.TryGetValue(showText.Count + (string.IsNullOrEmpty(imageLocation) ? 0 : 10000), out bottomData)) { ///初始化bottomData if (string.IsNullOrEmpty(imageLocation)) { bottomData = new BottomData(panel2, new TableLayoutPanel(), new KeyValuePair <Control, Control> [showText.Count]); } else { bottomData = new BottomData(panel2, new TableLayoutPanel(), new KeyValuePair <Control, Control> [showText.Count], new PictureBox(), new SplitContainer()); } _dicBottomData.Add(showText.Count + (string.IsNullOrEmpty(imageLocation) ? 0 : 10000), bottomData); } ///将其添加到底部 if (bottomData.HasImage) { if (panel2.Controls.Count == 0 || panel2.Controls[0] != bottomData.ImageSplitContainer) { panel2.Controls.Clear(); panel2.Controls.Add(bottomData.ImageSplitContainer); } } else { if (panel2.Controls.Count == 0 || panel2.Controls[0] != bottomData.MainTableLayoutPanel) { panel2.Controls.Clear(); panel2.Controls.Add(bottomData.MainTableLayoutPanel); } } ///设置Text值 KeyValuePair <Control, Control>[] keyvalues = bottomData.KeyValueControls; for (int i = 0; i < showText.Count; i++) { keyvalues[i].Key.Text = showText[i].Key; keyvalues[i].Value.Text = showText[i].Value; } ///设置图片地址 if (!string.IsNullOrEmpty(imageLocation)) { bottomData.PictureBox.ImageLocation = imageLocation; } }
//--- Methods --- /// <summary> /// Push an item onto the tail of the queue. /// </summary> /// <remarks> /// NOTE: Push() and TryPop() <strong>MUST</strong> be called from the same thread. /// </remarks> /// <param name="data">Item to push onto the tail of the queue.</param> public void Push(T data) { // read bottom data BottomData curBottom = _bottom; // write data in current bottom cell curBottom.Node.Data[curBottom.Index] = data; BottomData newBottom; if (curBottom.Index != 0) { newBottom = new BottomData(curBottom.Node, curBottom.Index - 1); } else { // allocate and link a new node DequeNode newNode = new DequeNode(_capacity, curBottom.Node); newBottom = new BottomData(newNode, _capacity - 1); } // update bottom _bottom = newBottom; }
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { BottomData bd = d as BottomData; bd.NotifyPropertyChanged("Value"); }
/// <summary> /// Pop an item from the tail of the queue. /// </summary> /// <remarks> /// NOTE: Push() and TryPop() <strong>MUST</strong> be called from the same thread. /// </remarks> /// <param name="item">Tail item of the queue when operation is successful.</param> /// <returns><see langword="True"/> if operation was successful.</returns> public bool TryPop(out T item) { item = default(T); // read bottom data BottomData curBottom = _bottom; BottomData newBottom; if (curBottom.Index != (_capacity - 1)) { newBottom = new BottomData(curBottom.Node, curBottom.Index + 1); } else { newBottom = new BottomData(curBottom.Node.Next, 0); } // update bottom _bottom = newBottom; // read top TopData curTop = _top; // read data to be popped T retVal = newBottom.Node.Data[newBottom.Index]; // case 1: if _top has crossed _bottom if (ReferenceEquals(curBottom.Node, curTop.Node) && (curBottom.Index == curTop.Index)) { // return bottom to its old position _bottom = curBottom; return(false); } // case 2: when popping the last entry in the deque (i.e. deque is empty after the update of bottom) if (ReferenceEquals(newBottom.Node, curTop.Node) && (newBottom.Index == curTop.Index)) { // try to update _top's tag so no concurrent Steal operation will also pop the same entry TopData newTopVal = new TopData(curTop.Tag + 1, curTop.Node, curTop.Index); if (SysUtil.CAS(ref _top, curTop, newTopVal)) { // TODO (steveb): clear out the entry we read, so the GC can reclaim it // free old node if needed if (!ReferenceEquals(curBottom.Node, newBottom.Node)) { newBottom.Node.Prev = null; } item = retVal; return(true); } else { // if CAS failed (i.e. a concurrent Steal operation alrady popped that last entry) // return bottom to its old position _bottom = curBottom; return(false); } } // case 3: regular case (i.e. there was a least one entry in the deque _after_ bottom's update) // free old node if needed if (!ReferenceEquals(curBottom.Node, newBottom.Node)) { newBottom.Node.Prev = null; } item = retVal; return(true); }